parsl 2024.10.14__tar.gz → 2024.10.21__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {parsl-2024.10.14/parsl.egg-info → parsl-2024.10.21}/PKG-INFO +2 -2
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/executor.py +16 -9
- parsl-2024.10.21/parsl/executors/high_throughput/manager_selector.py +55 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/process_worker_pool.py +1 -1
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/kubernetes/kube.py +35 -28
- parsl-2024.10.21/parsl/tests/test_htex/test_block_manager_selector_unit.py +20 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_drain.py +6 -4
- parsl-2024.10.21/parsl/tests/test_htex/test_manager_selector_by_block.py +53 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_resource_spec_validation.py +7 -0
- parsl-2024.10.21/parsl/tests/test_providers/test_kubernetes_provider.py +102 -0
- parsl-2024.10.21/parsl/tests/test_utils/test_sanitize_dns.py +76 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/utils.py +78 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/version.py +1 -1
- {parsl-2024.10.14 → parsl-2024.10.21/parsl.egg-info}/PKG-INFO +2 -2
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl.egg-info/SOURCES.txt +4 -0
- parsl-2024.10.14/parsl/executors/high_throughput/manager_selector.py +0 -25
- {parsl-2024.10.14 → parsl-2024.10.21}/LICENSE +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/MANIFEST.in +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/README.rst +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/addresses.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/app.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/bash.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/futures.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/app/python.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/benchmark/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/benchmark/perf.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/base.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/local/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/local/local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/oauth_ssh/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/oauth_ssh/oauth_ssh.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/ssh/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/ssh/ssh.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/ssh_il/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/channels/ssh_il/ssh_il.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/concurrent/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/config.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/ASPIRE1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/Azure.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/bridges.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/cc_in2p3.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/ec2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/expanse.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/frontera.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/htex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/illinoiscluster.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/improv.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/kubernetes.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/local_threads.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/midway.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/osg.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/polaris.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/stampede2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/summit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/toss3_llnl.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/vineex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/configs/wqex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/curvezmq.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/data_manager.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/file_noop.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/files.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/ftp.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/globus.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/http.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/rsync.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/staging.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/data_provider/zip.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/dependency_resolvers.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/dflow.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/futures.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/memoization.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/rundirs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/states.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/dataflow/taskrecord.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/base.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/flux/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/flux/execute_parsl_task.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/flux/executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/flux/flux_instance_manager.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/interchange.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/manager_record.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/monitoring_info.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/mpi_executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/mpi_resource_management.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/probe.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/zmq_pipes.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/radical/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/radical/executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/radical/rpex_resources.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/radical/rpex_worker.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/status_handling.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/factory.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/factory_config.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/manager.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/manager_config.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/taskvine/utils.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/threads.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/error_handlers.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/job_status_poller.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/states.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/jobs/strategy.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/launchers/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/launchers/base.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/launchers/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/launchers/launchers.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/log_utils.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/db_manager.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/message_type.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/monitoring.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/queries/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/queries/pandas.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/radios.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/remote.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/router.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/types.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/app.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/models.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/plots/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/app.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/dag.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/error.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/layout.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/task.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/workflow.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/utils.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/version.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/monitoring/visualization/views.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/multiprocessing.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/process_loggers.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/ad_hoc/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/ad_hoc/ad_hoc.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/aws/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/aws/aws.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/aws/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/azure/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/azure/azure.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/azure/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/base.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/cluster_provider.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/cobalt/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/cobalt/cobalt.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/cobalt/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/condor/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/condor/condor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/condor/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/googlecloud/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/googlecloud/googlecloud.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/grid_engine/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/grid_engine/grid_engine.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/grid_engine/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/kubernetes/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/kubernetes/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/local/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/local/local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/lsf/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/lsf/lsf.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/lsf/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/pbspro/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/pbspro/pbspro.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/pbspro/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/slurm/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/slurm/slurm.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/slurm/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/torque/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/torque/template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/providers/torque/torque.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/py.typed +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/base.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/concretes.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/facade.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/serialize/proxystore.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/callables_helper.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/azure_single_node.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/bluewaters.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/bridges.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/cc_in2p3.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/comet.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/cooley_htex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/ec2_single_node.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/ec2_spot.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/flux_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/frontera.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/htex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/htex_local_alternate.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_adhoc.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_radical.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_radical_mpi.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_checkpoint_periodic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_globus.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_monitoring.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/local_threads_no_cache.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/midway.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/nscc_singapore.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/osg_htex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/petrelkube.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/slurm_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/summit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/taskvine_ex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/theta.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/user_opts.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/configs/workqueue_ex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/conftest.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/latency.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_apps/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_channels/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_channels/test_channels.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_channels/test_local_channel.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_stress/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/htex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_log_filter.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_regression_220.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_udp_simple.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/manual_tests/test_worker_count.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/htex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/local_threads.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/test_scale.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/vineex_condor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/vineex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/wqex_condor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/scaling_tests/wqex_local.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/site_tests/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/site_tests/site_config_selector.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/site_tests/test_provider.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/site_tests/test_site.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_affinity.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_concurrent.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_dynamic_executor.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_ec2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_launchers.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_local_adhoc.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_mpi/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/sites/test_worker_info.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_aalst_patterns.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_inputs_default.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_std_uri.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_callables.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_channels/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_channels/test_dfk_close.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_channels/test_large_output.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_periodic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_python_checkpoint_3.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_curvezmq.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_from_slides.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_kwargs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_workflow1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_workflow2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_docs/test_workflow4.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_fail.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_rand_fail.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_retries.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_flowcontrol/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_flux.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_command_client_timeout.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_htex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_manager_failure.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_managers_command.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_missing_worker.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_worker_failure.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_app_names.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_fuzz_zmq.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_stdouterr.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_mpiex.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_cobalt_deprecation_warning.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_local_provider.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_slurm_template.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_context_manager.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_dependencies_deep.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_depfail_propagation.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_fail.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_futures.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_inputs_default.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_join.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_lifted.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_mapred.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_outputs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_overview.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_pluggable_future_resolution.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_simple.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_timeout.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_python_apps/test_type5.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_radical/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_1480.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_1653.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_221.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_226.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_2652.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_69a.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_854.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_regression/test_98.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_scale_down.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_scaling/test_shutdown_scalein.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_basic.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_pack_resource_spec.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_shutdown/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_shutdown/test_kill_monitoring.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/staging_provider.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_1316.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_docs_1.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_docs_2.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_file.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_file_apps.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_file_staging.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_output_chain_filenames.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_staging_globus.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_staging_https.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_staging_stdout.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_zip_in.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_zip_out.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_staging/test_zip_to_zip.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_summary.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_thread_parallelism.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_threads/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_threads/test_configs.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_utils/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/unit/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/unit/test_file.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/unit/test_usage_tracking.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/utils.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/usage_tracking/__init__.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/usage_tracking/api.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/usage_tracking/levels.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl/usage_tracking/usage.py +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl.egg-info/dependency_links.txt +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl.egg-info/entry_points.txt +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl.egg-info/requires.txt +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/parsl.egg-info/top_level.txt +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/requirements.txt +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/setup.cfg +0 -0
- {parsl-2024.10.14 → parsl-2024.10.21}/setup.py +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: parsl
|
3
|
-
Version: 2024.10.
|
3
|
+
Version: 2024.10.21
|
4
4
|
Summary: Simple data dependent workflows in Python
|
5
5
|
Home-page: https://github.com/Parsl/parsl
|
6
|
-
Download-URL: https://github.com/Parsl/parsl/archive/2024.10.
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2024.10.21.tar.gz
|
7
7
|
Author: The Parsl Team
|
8
8
|
Author-email: parsl@googlegroups.com
|
9
9
|
License: Apache 2.0
|
@@ -146,6 +146,11 @@ GENERAL_HTEX_PARAM_DOCS = """provider : :class:`~parsl.providers.base.ExecutionP
|
|
146
146
|
|
147
147
|
encrypted : bool
|
148
148
|
Flag to enable/disable encryption (CurveZMQ). Default is False.
|
149
|
+
|
150
|
+
manager_selector: ManagerSelector
|
151
|
+
Determines what strategy the interchange uses to select managers during task distribution.
|
152
|
+
See API reference under "Manager Selectors" regarding the various manager selectors.
|
153
|
+
Default: 'RandomManagerSelector'
|
149
154
|
""" # Documentation for params used by both HTEx and MPIEx
|
150
155
|
|
151
156
|
|
@@ -341,15 +346,17 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
341
346
|
return self.logdir
|
342
347
|
|
343
348
|
def validate_resource_spec(self, resource_specification: dict):
|
344
|
-
"""HTEX
|
345
|
-
|
349
|
+
"""HTEX supports the following *Optional* resource specifications:
|
350
|
+
priority: lower value is higher priority"""
|
346
351
|
if resource_specification:
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
352
|
+
acceptable_fields = {'priority'}
|
353
|
+
keys = set(resource_specification.keys())
|
354
|
+
invalid_keys = keys - acceptable_fields
|
355
|
+
if invalid_keys:
|
356
|
+
message = "Task resource specification only accepts these types of resources: {}".format(
|
357
|
+
', '.join(acceptable_fields))
|
358
|
+
logger.error(message)
|
359
|
+
raise InvalidResourceSpecification(set(invalid_keys), message)
|
353
360
|
return
|
354
361
|
|
355
362
|
def initialize_scaling(self):
|
@@ -657,7 +664,7 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
657
664
|
except TypeError:
|
658
665
|
raise SerializationError(func.__name__)
|
659
666
|
|
660
|
-
msg = {"task_id": task_id, "buffer": fn_buf}
|
667
|
+
msg = {"task_id": task_id, "resource_spec": resource_specification, "buffer": fn_buf}
|
661
668
|
|
662
669
|
# Post task to the outgoing queue
|
663
670
|
self.outgoing_q.put(msg)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import random
|
2
|
+
from abc import ABCMeta, abstractmethod
|
3
|
+
from typing import Dict, List, Set
|
4
|
+
|
5
|
+
from parsl.executors.high_throughput.manager_record import ManagerRecord
|
6
|
+
|
7
|
+
|
8
|
+
class ManagerSelector(metaclass=ABCMeta):
|
9
|
+
|
10
|
+
@abstractmethod
|
11
|
+
def sort_managers(self, ready_managers: Dict[bytes, ManagerRecord], manager_list: Set[bytes]) -> List[bytes]:
|
12
|
+
""" Sort a given list of managers.
|
13
|
+
|
14
|
+
Any operations pertaining to the sorting and rearrangement of the
|
15
|
+
interesting_managers Set should be performed here.
|
16
|
+
"""
|
17
|
+
pass
|
18
|
+
|
19
|
+
|
20
|
+
class RandomManagerSelector(ManagerSelector):
|
21
|
+
|
22
|
+
"""Returns a shuffled list of interesting_managers
|
23
|
+
|
24
|
+
By default this strategy is used by the interchange. Works well
|
25
|
+
in distributing workloads equally across all availble compute
|
26
|
+
resources. The random workload strategy is not effective in
|
27
|
+
conjunction with elastic scaling behavior as the even task
|
28
|
+
distribution does not allow the scaling down of blocks, leading
|
29
|
+
to wasted resource consumption.
|
30
|
+
"""
|
31
|
+
|
32
|
+
def sort_managers(self, ready_managers: Dict[bytes, ManagerRecord], manager_list: Set[bytes]) -> List[bytes]:
|
33
|
+
c_manager_list = list(manager_list)
|
34
|
+
random.shuffle(c_manager_list)
|
35
|
+
return c_manager_list
|
36
|
+
|
37
|
+
|
38
|
+
class BlockIdManagerSelector(ManagerSelector):
|
39
|
+
|
40
|
+
"""Returns an interesting_managers list sorted by block ID
|
41
|
+
|
42
|
+
Observations:
|
43
|
+
1. BlockID manager selector helps with workloads that see a varying
|
44
|
+
amount of tasks over time. New blocks are prioritized with the
|
45
|
+
blockID manager selector, when used with 'htex_auto_scaling', results
|
46
|
+
in compute cost savings.
|
47
|
+
|
48
|
+
2. Doesn't really work with bag-of-tasks workloads. When all the tasks
|
49
|
+
are put into the queue upfront, all blocks operate at near full
|
50
|
+
utilization for the majority of the workload, which task goes where
|
51
|
+
doesn't really matter.
|
52
|
+
"""
|
53
|
+
|
54
|
+
def sort_managers(self, ready_managers: Dict[bytes, ManagerRecord], manager_list: Set[bytes]) -> List[bytes]:
|
55
|
+
return sorted(manager_list, key=lambda x: (ready_managers[x]['block_id'] is not None, ready_managers[x]['block_id']))
|
{parsl-2024.10.14 → parsl-2024.10.21}/parsl/executors/high_throughput/process_worker_pool.py
RENAMED
@@ -362,7 +362,7 @@ class Manager:
|
|
362
362
|
if tasks == HEARTBEAT_CODE:
|
363
363
|
logger.debug("Got heartbeat from interchange")
|
364
364
|
elif tasks == DRAINED_CODE:
|
365
|
-
logger.info("Got
|
365
|
+
logger.info("Got fully drained message from interchange - setting kill flag")
|
366
366
|
kill_event.set()
|
367
367
|
else:
|
368
368
|
task_recv_counter += len(tasks)
|
@@ -1,10 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
import
|
3
|
-
|
4
|
-
from parsl.providers.kubernetes.template import template_string
|
5
|
-
|
6
|
-
logger = logging.getLogger(__name__)
|
7
|
-
|
2
|
+
import uuid
|
8
3
|
from typing import Any, Dict, List, Optional, Tuple
|
9
4
|
|
10
5
|
import typeguard
|
@@ -12,7 +7,8 @@ import typeguard
|
|
12
7
|
from parsl.errors import OptionalModuleMissing
|
13
8
|
from parsl.jobs.states import JobState, JobStatus
|
14
9
|
from parsl.providers.base import ExecutionProvider
|
15
|
-
from parsl.
|
10
|
+
from parsl.providers.kubernetes.template import template_string
|
11
|
+
from parsl.utils import RepresentationMixin, sanitize_dns_subdomain_rfc1123
|
16
12
|
|
17
13
|
try:
|
18
14
|
from kubernetes import client, config
|
@@ -20,6 +16,8 @@ try:
|
|
20
16
|
except (ImportError, NameError, FileNotFoundError):
|
21
17
|
_kubernetes_enabled = False
|
22
18
|
|
19
|
+
logger = logging.getLogger(__name__)
|
20
|
+
|
23
21
|
translate_table = {
|
24
22
|
'Running': JobState.RUNNING,
|
25
23
|
'Pending': JobState.PENDING,
|
@@ -161,7 +159,7 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
161
159
|
self.resources: Dict[object, Dict[str, Any]]
|
162
160
|
self.resources = {}
|
163
161
|
|
164
|
-
def submit(self, cmd_string, tasks_per_node, job_name="parsl"):
|
162
|
+
def submit(self, cmd_string: str, tasks_per_node: int, job_name: str = "parsl.kube"):
|
165
163
|
""" Submit a job
|
166
164
|
Args:
|
167
165
|
- cmd_string :(String) - Name of the container to initiate
|
@@ -173,15 +171,19 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
173
171
|
Returns:
|
174
172
|
- job_id: (string) Identifier for the job
|
175
173
|
"""
|
174
|
+
job_id = uuid.uuid4().hex[:8]
|
176
175
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
176
|
+
pod_name = self.pod_name or job_name
|
177
|
+
try:
|
178
|
+
pod_name = sanitize_dns_subdomain_rfc1123(pod_name)
|
179
|
+
except ValueError:
|
180
|
+
logger.warning(
|
181
|
+
f"Invalid pod name '{pod_name}' for job '{job_id}', falling back to 'parsl.kube'"
|
182
|
+
)
|
183
|
+
pod_name = "parsl.kube"
|
184
|
+
pod_name = pod_name[:253 - 1 - len(job_id)] # Leave room for the job ID
|
185
|
+
pod_name = pod_name.rstrip(".-") # Remove trailing dot or hyphen after trim
|
186
|
+
pod_name = f"{pod_name}.{job_id}"
|
185
187
|
|
186
188
|
formatted_cmd = template_string.format(command=cmd_string,
|
187
189
|
worker_init=self.worker_init)
|
@@ -189,14 +191,14 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
189
191
|
logger.debug("Pod name: %s", pod_name)
|
190
192
|
self._create_pod(image=self.image,
|
191
193
|
pod_name=pod_name,
|
192
|
-
|
194
|
+
job_id=job_id,
|
193
195
|
cmd_string=formatted_cmd,
|
194
196
|
volumes=self.persistent_volumes,
|
195
197
|
service_account_name=self.service_account_name,
|
196
198
|
annotations=self.annotations)
|
197
|
-
self.resources[
|
199
|
+
self.resources[job_id] = {'status': JobStatus(JobState.RUNNING), 'pod_name': pod_name}
|
198
200
|
|
199
|
-
return
|
201
|
+
return job_id
|
200
202
|
|
201
203
|
def status(self, job_ids):
|
202
204
|
""" Get the status of a list of jobs identified by the job identifiers
|
@@ -212,6 +214,9 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
212
214
|
self._status()
|
213
215
|
return [self.resources[jid]['status'] for jid in job_ids]
|
214
216
|
|
217
|
+
def _get_pod_name(self, job_id: str) -> str:
|
218
|
+
return self.resources[job_id]['pod_name']
|
219
|
+
|
215
220
|
def cancel(self, job_ids):
|
216
221
|
""" Cancels the jobs specified by a list of job ids
|
217
222
|
Args:
|
@@ -221,7 +226,8 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
221
226
|
"""
|
222
227
|
for job in job_ids:
|
223
228
|
logger.debug("Terminating job/pod: {0}".format(job))
|
224
|
-
self.
|
229
|
+
pod_name = self._get_pod_name(job)
|
230
|
+
self._delete_pod(pod_name)
|
225
231
|
|
226
232
|
self.resources[job]['status'] = JobStatus(JobState.CANCELLED)
|
227
233
|
rets = [True for i in job_ids]
|
@@ -242,7 +248,8 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
242
248
|
for jid in to_poll_job_ids:
|
243
249
|
phase = None
|
244
250
|
try:
|
245
|
-
|
251
|
+
pod_name = self._get_pod_name(jid)
|
252
|
+
pod = self.kube_client.read_namespaced_pod(name=pod_name, namespace=self.namespace)
|
246
253
|
except Exception:
|
247
254
|
logger.exception("Failed to poll pod {} status, most likely because pod was terminated".format(jid))
|
248
255
|
if self.resources[jid]['status'] is JobStatus(JobState.RUNNING):
|
@@ -257,10 +264,10 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
257
264
|
self.resources[jid]['status'] = JobStatus(status)
|
258
265
|
|
259
266
|
def _create_pod(self,
|
260
|
-
image,
|
261
|
-
pod_name,
|
262
|
-
|
263
|
-
port=80,
|
267
|
+
image: str,
|
268
|
+
pod_name: str,
|
269
|
+
job_id: str,
|
270
|
+
port: int = 80,
|
264
271
|
cmd_string=None,
|
265
272
|
volumes=[],
|
266
273
|
service_account_name=None,
|
@@ -269,7 +276,7 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
269
276
|
Args:
|
270
277
|
- image (string) : Docker image to launch
|
271
278
|
- pod_name (string) : Name of the pod
|
272
|
-
-
|
279
|
+
- job_id (string) : Job ID
|
273
280
|
KWargs:
|
274
281
|
- port (integer) : Container port
|
275
282
|
Returns:
|
@@ -299,7 +306,7 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
299
306
|
)
|
300
307
|
# Configure Pod template container
|
301
308
|
container = client.V1Container(
|
302
|
-
name=
|
309
|
+
name=job_id,
|
303
310
|
image=image,
|
304
311
|
resources=resources,
|
305
312
|
ports=[client.V1ContainerPort(container_port=port)],
|
@@ -322,7 +329,7 @@ class KubernetesProvider(ExecutionProvider, RepresentationMixin):
|
|
322
329
|
claim_name=volume[0])))
|
323
330
|
|
324
331
|
metadata = client.V1ObjectMeta(name=pod_name,
|
325
|
-
labels={"
|
332
|
+
labels={"parsl-job-id": job_id},
|
326
333
|
annotations=annotations)
|
327
334
|
spec = client.V1PodSpec(containers=[container],
|
328
335
|
image_pull_secrets=[secret],
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from parsl.executors.high_throughput.manager_record import ManagerRecord
|
4
|
+
from parsl.executors.high_throughput.manager_selector import BlockIdManagerSelector
|
5
|
+
|
6
|
+
|
7
|
+
@pytest.mark.local
|
8
|
+
def test_sort_managers():
|
9
|
+
ready_managers = {
|
10
|
+
b'manager1': {'block_id': 1},
|
11
|
+
b'manager2': {'block_id': None},
|
12
|
+
b'manager3': {'block_id': 3},
|
13
|
+
b'manager4': {'block_id': 2}
|
14
|
+
}
|
15
|
+
|
16
|
+
manager_list = {b'manager1', b'manager2', b'manager3', b'manager4'}
|
17
|
+
expected_sorted_list = [b'manager2', b'manager1', b'manager4', b'manager3']
|
18
|
+
manager_selector = BlockIdManagerSelector()
|
19
|
+
sorted_managers = manager_selector.sort_managers(ready_managers, manager_list)
|
20
|
+
assert sorted_managers == expected_sorted_list
|
@@ -13,7 +13,9 @@ from parsl.providers import LocalProvider
|
|
13
13
|
# based around the expected drain period: the drain period
|
14
14
|
# is TIME_CONST seconds, and the single executed task will
|
15
15
|
# last twice that many number of seconds.
|
16
|
-
TIME_CONST =
|
16
|
+
TIME_CONST = 4
|
17
|
+
|
18
|
+
CONNECTED_MANAGERS_POLL_MS = 100
|
17
19
|
|
18
20
|
|
19
21
|
def local_config():
|
@@ -52,7 +54,7 @@ def test_drain(try_assert):
|
|
52
54
|
|
53
55
|
# wait till we have a block running...
|
54
56
|
|
55
|
-
try_assert(lambda: len(htex.connected_managers()) == 1)
|
57
|
+
try_assert(lambda: len(htex.connected_managers()) == 1, check_period_ms=CONNECTED_MANAGERS_POLL_MS)
|
56
58
|
|
57
59
|
managers = htex.connected_managers()
|
58
60
|
assert managers[0]['active'], "The manager should be active"
|
@@ -63,7 +65,7 @@ def test_drain(try_assert):
|
|
63
65
|
time.sleep(TIME_CONST)
|
64
66
|
|
65
67
|
# this assert should happen *very fast* after the above delay...
|
66
|
-
try_assert(lambda: htex.connected_managers()[0]['draining'], timeout_ms=500)
|
68
|
+
try_assert(lambda: htex.connected_managers()[0]['draining'], timeout_ms=500, check_period_ms=CONNECTED_MANAGERS_POLL_MS)
|
67
69
|
|
68
70
|
# and the test task should still be running...
|
69
71
|
assert not fut.done(), "The test task should still be running"
|
@@ -76,4 +78,4 @@ def test_drain(try_assert):
|
|
76
78
|
# connected managers.
|
77
79
|
# As with the above draining assert, this should happen very fast after
|
78
80
|
# the task ends.
|
79
|
-
try_assert(lambda: len(htex.connected_managers()) == 0, timeout_ms=500)
|
81
|
+
try_assert(lambda: len(htex.connected_managers()) == 0, timeout_ms=500, check_period_ms=CONNECTED_MANAGERS_POLL_MS)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
|
5
|
+
import parsl
|
6
|
+
from parsl.app.app import bash_app, python_app
|
7
|
+
from parsl.channels import LocalChannel
|
8
|
+
from parsl.config import Config
|
9
|
+
from parsl.executors import HighThroughputExecutor
|
10
|
+
from parsl.executors.high_throughput.manager_selector import (
|
11
|
+
BlockIdManagerSelector,
|
12
|
+
ManagerSelector,
|
13
|
+
)
|
14
|
+
from parsl.launchers import WrappedLauncher
|
15
|
+
from parsl.providers import LocalProvider
|
16
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
17
|
+
|
18
|
+
BLOCK_COUNT = 2
|
19
|
+
|
20
|
+
|
21
|
+
@parsl.python_app
|
22
|
+
def get_worker_pid():
|
23
|
+
import os
|
24
|
+
return os.environ.get('PARSL_WORKER_BLOCK_ID')
|
25
|
+
|
26
|
+
|
27
|
+
@pytest.mark.local
|
28
|
+
def test_block_id_selection(try_assert):
|
29
|
+
htex = HighThroughputExecutor(
|
30
|
+
label="htex_local",
|
31
|
+
max_workers_per_node=1,
|
32
|
+
manager_selector=BlockIdManagerSelector(),
|
33
|
+
provider=LocalProvider(
|
34
|
+
channel=LocalChannel(),
|
35
|
+
init_blocks=BLOCK_COUNT,
|
36
|
+
max_blocks=BLOCK_COUNT,
|
37
|
+
min_blocks=BLOCK_COUNT,
|
38
|
+
),
|
39
|
+
)
|
40
|
+
|
41
|
+
config = Config(
|
42
|
+
executors=[htex],
|
43
|
+
usage_tracking=LEVEL_1,
|
44
|
+
)
|
45
|
+
|
46
|
+
with parsl.load(config):
|
47
|
+
blockids = []
|
48
|
+
try_assert(lambda: len(htex.connected_managers()) == BLOCK_COUNT, timeout_ms=20000)
|
49
|
+
for i in range(10):
|
50
|
+
future = get_worker_pid()
|
51
|
+
blockids.append(future.result())
|
52
|
+
|
53
|
+
assert all(blockid == "1" for blockid in blockids)
|
{parsl-2024.10.14 → parsl-2024.10.21}/parsl/tests/test_htex/test_resource_spec_validation.py
RENAMED
@@ -30,6 +30,13 @@ def test_resource_spec_validation():
|
|
30
30
|
assert ret_val is None
|
31
31
|
|
32
32
|
|
33
|
+
@pytest.mark.local
|
34
|
+
def test_resource_spec_validation_one_key():
|
35
|
+
htex = HighThroughputExecutor()
|
36
|
+
ret_val = htex.validate_resource_spec({"priority": 2})
|
37
|
+
assert ret_val is None
|
38
|
+
|
39
|
+
|
33
40
|
@pytest.mark.local
|
34
41
|
def test_resource_spec_validation_bad_keys():
|
35
42
|
htex = HighThroughputExecutor()
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import re
|
2
|
+
from unittest import mock
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from parsl.providers.kubernetes.kube import KubernetesProvider
|
7
|
+
from parsl.tests.test_utils.test_sanitize_dns import DNS_SUBDOMAIN_REGEX
|
8
|
+
|
9
|
+
_MOCK_BASE = "parsl.providers.kubernetes.kube"
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture(autouse=True)
|
13
|
+
def mock_kube_config():
|
14
|
+
with mock.patch(f"{_MOCK_BASE}.config") as mock_config:
|
15
|
+
mock_config.load_kube_config.return_value = None
|
16
|
+
yield mock_config
|
17
|
+
|
18
|
+
|
19
|
+
@pytest.fixture
|
20
|
+
def mock_kube_client():
|
21
|
+
mock_client = mock.MagicMock()
|
22
|
+
with mock.patch(f"{_MOCK_BASE}.client.CoreV1Api") as mock_api:
|
23
|
+
mock_api.return_value = mock_client
|
24
|
+
yield mock_client
|
25
|
+
|
26
|
+
|
27
|
+
@pytest.mark.local
|
28
|
+
def test_submit_happy_path(mock_kube_client: mock.MagicMock):
|
29
|
+
image = "test-image"
|
30
|
+
namespace = "test-namespace"
|
31
|
+
cmd_string = "test-command"
|
32
|
+
volumes = [("test-volume", "test-mount-path")]
|
33
|
+
service_account_name = "test-service-account"
|
34
|
+
annotations = {"test-annotation": "test-value"}
|
35
|
+
max_cpu = 2
|
36
|
+
max_mem = "2Gi"
|
37
|
+
init_cpu = 1
|
38
|
+
init_mem = "1Gi"
|
39
|
+
provider = KubernetesProvider(
|
40
|
+
image=image,
|
41
|
+
persistent_volumes=volumes,
|
42
|
+
namespace=namespace,
|
43
|
+
service_account_name=service_account_name,
|
44
|
+
annotations=annotations,
|
45
|
+
max_cpu=max_cpu,
|
46
|
+
max_mem=max_mem,
|
47
|
+
init_cpu=init_cpu,
|
48
|
+
init_mem=init_mem,
|
49
|
+
)
|
50
|
+
|
51
|
+
job_name = "test.job.name"
|
52
|
+
job_id = provider.submit(cmd_string=cmd_string, tasks_per_node=1, job_name=job_name)
|
53
|
+
|
54
|
+
assert job_id in provider.resources
|
55
|
+
assert mock_kube_client.create_namespaced_pod.call_count == 1
|
56
|
+
|
57
|
+
call_args = mock_kube_client.create_namespaced_pod.call_args[1]
|
58
|
+
pod = call_args["body"]
|
59
|
+
container = pod.spec.containers[0]
|
60
|
+
volume = container.volume_mounts[0]
|
61
|
+
|
62
|
+
assert image == container.image
|
63
|
+
assert namespace == call_args["namespace"]
|
64
|
+
assert any(cmd_string in arg for arg in container.args)
|
65
|
+
assert volumes[0] == (volume.name, volume.mount_path)
|
66
|
+
assert service_account_name == pod.spec.service_account_name
|
67
|
+
assert annotations == pod.metadata.annotations
|
68
|
+
assert str(max_cpu) == container.resources.limits["cpu"]
|
69
|
+
assert max_mem == container.resources.limits["memory"]
|
70
|
+
assert str(init_cpu) == container.resources.requests["cpu"]
|
71
|
+
assert init_mem == container.resources.requests["memory"]
|
72
|
+
assert job_id == pod.metadata.labels["parsl-job-id"]
|
73
|
+
assert job_id == container.name
|
74
|
+
assert f"{job_name}.{job_id}" == pod.metadata.name
|
75
|
+
|
76
|
+
|
77
|
+
@pytest.mark.local
|
78
|
+
@mock.patch(f"{_MOCK_BASE}.KubernetesProvider._create_pod")
|
79
|
+
@pytest.mark.parametrize("char", (".", "-"))
|
80
|
+
def test_submit_pod_name_includes_job_id(mock_create_pod: mock.MagicMock, char: str):
|
81
|
+
provider = KubernetesProvider(image="test-image")
|
82
|
+
|
83
|
+
job_name = "a." * 121 + f"a{char}" + "a" * 9
|
84
|
+
assert len(job_name) == 253 # Max length for pod name
|
85
|
+
job_id = provider.submit(cmd_string="test-command", tasks_per_node=1, job_name=job_name)
|
86
|
+
|
87
|
+
expected_pod_name = job_name[:253 - len(job_id) - 2] + f".{job_id}"
|
88
|
+
actual_pod_name = mock_create_pod.call_args[1]["pod_name"]
|
89
|
+
assert re.match(DNS_SUBDOMAIN_REGEX, actual_pod_name)
|
90
|
+
assert expected_pod_name == actual_pod_name
|
91
|
+
|
92
|
+
|
93
|
+
@pytest.mark.local
|
94
|
+
@mock.patch(f"{_MOCK_BASE}.KubernetesProvider._create_pod")
|
95
|
+
@mock.patch(f"{_MOCK_BASE}.logger")
|
96
|
+
@pytest.mark.parametrize("job_name", ("", ".", "-", "a.-.a", "$$$"))
|
97
|
+
def test_submit_invalid_job_name(mock_logger: mock.MagicMock, mock_create_pod: mock.MagicMock, job_name: str):
|
98
|
+
provider = KubernetesProvider(image="test-image")
|
99
|
+
job_id = provider.submit(cmd_string="test-command", tasks_per_node=1, job_name=job_name)
|
100
|
+
assert mock_logger.warning.call_count == 1
|
101
|
+
assert f"Invalid pod name '{job_name}' for job '{job_id}'" in mock_logger.warning.call_args[0][0]
|
102
|
+
assert f"parsl.kube.{job_id}" == mock_create_pod.call_args[1]["pod_name"]
|
@@ -0,0 +1,76 @@
|
|
1
|
+
import random
|
2
|
+
import re
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from parsl.utils import sanitize_dns_label_rfc1123, sanitize_dns_subdomain_rfc1123
|
7
|
+
|
8
|
+
# Ref: https://datatracker.ietf.org/doc/html/rfc1123
|
9
|
+
DNS_LABEL_REGEX = r'^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$'
|
10
|
+
DNS_SUBDOMAIN_REGEX = r'^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?(\.[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?)*$'
|
11
|
+
|
12
|
+
test_labels = [
|
13
|
+
"example-label-123", # Valid label
|
14
|
+
"EXAMPLE", # Case sensitivity
|
15
|
+
"!@#example*", # Remove invalid characters
|
16
|
+
"--leading-and-trailing--", # Leading and trailing hyphens
|
17
|
+
"..leading.and.trailing..", # Leading and tailing dots
|
18
|
+
"multiple..dots", # Consecutive dots
|
19
|
+
"valid--label", # Consecutive hyphens
|
20
|
+
"a" * random.randint(64, 70), # Longer than 63 characters
|
21
|
+
f"{'a' * 62}-a", # Trailing hyphen at max length
|
22
|
+
]
|
23
|
+
|
24
|
+
|
25
|
+
def _generate_test_subdomains(num_subdomains: int):
|
26
|
+
subdomains = []
|
27
|
+
for _ in range(num_subdomains):
|
28
|
+
num_labels = random.randint(1, 5)
|
29
|
+
labels = [test_labels[random.randint(0, num_labels - 1)] for _ in range(num_labels)]
|
30
|
+
subdomain = ".".join(labels)
|
31
|
+
subdomains.append(subdomain)
|
32
|
+
return subdomains
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.mark.local
|
36
|
+
@pytest.mark.parametrize("raw_string", test_labels)
|
37
|
+
def test_sanitize_dns_label_rfc1123(raw_string: str):
|
38
|
+
print(sanitize_dns_label_rfc1123(raw_string))
|
39
|
+
assert re.match(DNS_LABEL_REGEX, sanitize_dns_label_rfc1123(raw_string))
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.mark.local
|
43
|
+
@pytest.mark.parametrize("raw_string", ("", "-", "@", "$$$"))
|
44
|
+
def test_sanitize_dns_label_rfc1123_empty(raw_string: str):
|
45
|
+
with pytest.raises(ValueError) as e_info:
|
46
|
+
sanitize_dns_label_rfc1123(raw_string)
|
47
|
+
assert str(e_info.value) == f"Sanitized DNS label is empty for input '{raw_string}'"
|
48
|
+
|
49
|
+
|
50
|
+
@pytest.mark.local
|
51
|
+
@pytest.mark.parametrize("raw_string", _generate_test_subdomains(10))
|
52
|
+
def test_sanitize_dns_subdomain_rfc1123(raw_string: str):
|
53
|
+
assert re.match(DNS_SUBDOMAIN_REGEX, sanitize_dns_subdomain_rfc1123(raw_string))
|
54
|
+
|
55
|
+
|
56
|
+
@pytest.mark.local
|
57
|
+
@pytest.mark.parametrize("char", ("-", "."))
|
58
|
+
def test_sanitize_dns_subdomain_rfc1123_trailing_non_alphanumeric_at_max_length(char: str):
|
59
|
+
raw_string = (f"{'a' * 61}." * 4) + f".aaaa{char}a"
|
60
|
+
assert re.match(DNS_SUBDOMAIN_REGEX, sanitize_dns_subdomain_rfc1123(raw_string))
|
61
|
+
|
62
|
+
|
63
|
+
@pytest.mark.local
|
64
|
+
@pytest.mark.parametrize("raw_string", ("", ".", "..."))
|
65
|
+
def test_sanitize_dns_subdomain_rfc1123_empty(raw_string: str):
|
66
|
+
with pytest.raises(ValueError) as e_info:
|
67
|
+
sanitize_dns_subdomain_rfc1123(raw_string)
|
68
|
+
assert str(e_info.value) == f"Sanitized DNS subdomain is empty for input '{raw_string}'"
|
69
|
+
|
70
|
+
|
71
|
+
@pytest.mark.local
|
72
|
+
@pytest.mark.parametrize(
|
73
|
+
"raw_string", ("a" * 253, "a" * random.randint(254, 300)), ids=("254 chars", ">253 chars")
|
74
|
+
)
|
75
|
+
def test_sanitize_dns_subdomain_rfc1123_max_length(raw_string: str):
|
76
|
+
assert len(sanitize_dns_subdomain_rfc1123(raw_string)) <= 253
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import inspect
|
2
2
|
import logging
|
3
3
|
import os
|
4
|
+
import re
|
4
5
|
import shlex
|
5
6
|
import subprocess
|
6
7
|
import threading
|
@@ -380,3 +381,80 @@ class AutoCancelTimer(threading.Timer):
|
|
380
381
|
exc_tb: Optional[TracebackType]
|
381
382
|
) -> None:
|
382
383
|
self.cancel()
|
384
|
+
|
385
|
+
|
386
|
+
def sanitize_dns_label_rfc1123(raw_string: str) -> str:
|
387
|
+
"""Convert input string to a valid RFC 1123 DNS label.
|
388
|
+
|
389
|
+
Parameters
|
390
|
+
----------
|
391
|
+
raw_string : str
|
392
|
+
String to sanitize.
|
393
|
+
|
394
|
+
Returns
|
395
|
+
-------
|
396
|
+
str
|
397
|
+
Sanitized string.
|
398
|
+
|
399
|
+
Raises
|
400
|
+
------
|
401
|
+
ValueError
|
402
|
+
If the string is empty after sanitization.
|
403
|
+
"""
|
404
|
+
# Convert to lowercase and replace non-alphanumeric characters with hyphen
|
405
|
+
sanitized = re.sub(r'[^a-z0-9]', '-', raw_string.lower())
|
406
|
+
|
407
|
+
# Remove consecutive hyphens
|
408
|
+
sanitized = re.sub(r'-+', '-', sanitized)
|
409
|
+
|
410
|
+
# DNS label cannot exceed 63 characters
|
411
|
+
sanitized = sanitized[:63]
|
412
|
+
|
413
|
+
# Strip after trimming to avoid trailing hyphens
|
414
|
+
sanitized = sanitized.strip("-")
|
415
|
+
|
416
|
+
if not sanitized:
|
417
|
+
raise ValueError(f"Sanitized DNS label is empty for input '{raw_string}'")
|
418
|
+
|
419
|
+
return sanitized
|
420
|
+
|
421
|
+
|
422
|
+
def sanitize_dns_subdomain_rfc1123(raw_string: str) -> str:
|
423
|
+
"""Convert input string to a valid RFC 1123 DNS subdomain.
|
424
|
+
|
425
|
+
Parameters
|
426
|
+
----------
|
427
|
+
raw_string : str
|
428
|
+
String to sanitize.
|
429
|
+
|
430
|
+
Returns
|
431
|
+
-------
|
432
|
+
str
|
433
|
+
Sanitized string.
|
434
|
+
|
435
|
+
Raises
|
436
|
+
------
|
437
|
+
ValueError
|
438
|
+
If the string is empty after sanitization.
|
439
|
+
"""
|
440
|
+
segments = raw_string.split('.')
|
441
|
+
|
442
|
+
sanitized_segments = []
|
443
|
+
for segment in segments:
|
444
|
+
if not segment:
|
445
|
+
continue
|
446
|
+
sanitized_segment = sanitize_dns_label_rfc1123(segment)
|
447
|
+
sanitized_segments.append(sanitized_segment)
|
448
|
+
|
449
|
+
sanitized = '.'.join(sanitized_segments)
|
450
|
+
|
451
|
+
# DNS subdomain cannot exceed 253 characters
|
452
|
+
sanitized = sanitized[:253]
|
453
|
+
|
454
|
+
# Strip after trimming to avoid trailing dots or hyphens
|
455
|
+
sanitized = sanitized.strip(".-")
|
456
|
+
|
457
|
+
if not sanitized:
|
458
|
+
raise ValueError(f"Sanitized DNS subdomain is empty for input '{raw_string}'")
|
459
|
+
|
460
|
+
return sanitized
|