dpdispatcher 0.6.11__tar.gz → 0.6.12__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 dpdispatcher might be problematic. Click here for more details.
- dpdispatcher-0.6.12/.github/workflows/copilot-setup-steps.yml +65 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/machines.yml +7 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/pyright.yml +7 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/release.yml +10 -2
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/test-bohrium.yml +6 -2
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/test.yml +9 -5
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.gitignore +15 -1
- dpdispatcher-0.6.12/AGENTS.md +172 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/PKG-INFO +1 -1
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh/docker-compose.yml +12 -0
- dpdispatcher-0.6.12/ci/ssh/start-ssh.sh +28 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/context.md +22 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/_version.py +3 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/dp_cloud_server_context.py +3 -1
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/lazy_local_context.py +2 -2
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/openapi_context.py +6 -4
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/ssh_context.py +38 -7
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machine.py +1 -1
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/JH_UniScheduler.py +0 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/fugaku.py +0 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/lsf.py +0 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/openapi.py +3 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/pbs.py +0 -6
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/shell.py +0 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/slurm.py +0 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/client.py +5 -5
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/utils.py +20 -6
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/PKG-INFO +1 -1
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/SOURCES.txt +6 -0
- dpdispatcher-0.6.12/examples/machine/ssh_proxy_command.json +13 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/pyproject.toml +2 -3
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_examples.py +1 -0
- dpdispatcher-0.6.12/tests/test_rsync_flags.py +87 -0
- dpdispatcher-0.6.12/tests/test_rsync_proxy.py +130 -0
- dpdispatcher-0.6.12/tests/test_ssh_jump_host.py +90 -0
- dpdispatcher-0.6.11/ci/ssh/start-ssh.sh +0 -6
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.git_archival.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.gitattributes +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/dependabot.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/ci-docker.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/mirror_gitee.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/publish_conda.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.pre-commit-config.yaml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.readthedocs.yaml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/CONTRIBUTING.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/Dockerfile +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/LICENSE +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/README.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/LICENSE +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/README.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs/docker-compose.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs/start-pbs.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/docker-compose.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/register_cluster.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/start-slurm.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh_rsync.sh +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/codecov.yml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/conda/conda_build_config.yaml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/conda/meta.yaml +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/.gitignore +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/Makefile +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/batch.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/cli.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/conf.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/credits.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/dpdispatcher_on_yarn.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/env.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/expanse.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/g16.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/shell.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/template.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/getting-started.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/index.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/install.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/machine.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/make.bat +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/pep723.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/requirements.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/resources.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/run.md +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/task.rst +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/__main__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/arginfo.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/base_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/hdfs_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/local_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dlog.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpcloudserver/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpcloudserver/client.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpdisp.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/gui.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/run.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/submission.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/distributed_shell.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/dp_cloud_server.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/run.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/submission.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/config.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/retcode.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/zip_file.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/hdfs_cli.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/job_status.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/record.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/dependency_links.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/entry_points.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/requires.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/top_level.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/dpdisp_run.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/expanse.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/lazy_local.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/mandu.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/expanse_cpu.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/mandu.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/template.slurm +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/tiger.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/task/deepmd-kit.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/task/g16.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/scripts/script_gen_dargs_docs.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/scripts/script_gen_dargs_json.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/setup.cfg +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/.gitignore +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/__init__.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/batch.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/debug_test_class_submission_init.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_JH_UniScheduler.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_ali_ehpc.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_dp_cloud_server.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_lazy_ali_ehpc.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_lsf.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_shell.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_slurm.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_ssh_ali_ehpc.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/hello_world.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/job.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_JH_UniScheduler.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_ali_ehpc.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_center.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_diffenert.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_dp_cloud_server.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_fugaku.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_if_cuda_multi_devices.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_jh_unischeduler.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_lsf.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_slurm.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazylocal_shell.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_local_fugaku.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_local_shell.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lsf.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_openapi.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_slurm.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_yarn.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/resources.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/submission.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/task.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/sample_class.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/script_gen_json.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/slurm_test.env +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_JH_UniScheduler_script_generation.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_argcheck.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_job.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_machine.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_machine_dispatch.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_resources.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_submission.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_submission_init.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_task.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_cli.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/some_dir/some_file +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/dir with space/file with space +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/some_dir/some_file +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_group_size.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_gui.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_if_cuda_multi_devices/test_dir/test.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_import_classes.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lazy_local_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_local_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/submission.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_script_generation.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_retry.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission_bohrium.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission_ratio_unfinished.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_cuda_multi_devices.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/fail_dir/mock_fail_task.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir with space/example.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir1/example.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir2/example.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir3/example.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir4/example.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/recover_dir/mock_recover_task.txt +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-1/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-1/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-2/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-2/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-3/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-3/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-4/conf.lmp +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-4/input.lammps +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/d3c842c5b9476e48f7145b370cd330372b9293e1.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/graph.pb +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/submission.json +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_script_generation.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_ssh_context.py +0 -0
- {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_work_path/.gitkeep +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: "Copilot Setup Steps"
|
|
2
|
+
|
|
3
|
+
# Automatically run the setup steps when they are changed to allow for easy validation, and
|
|
4
|
+
# allow manual testing through the repository's "Actions" tab
|
|
5
|
+
on:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
push:
|
|
8
|
+
paths:
|
|
9
|
+
- .github/workflows/copilot-setup-steps.yml
|
|
10
|
+
pull_request:
|
|
11
|
+
paths:
|
|
12
|
+
- .github/workflows/copilot-setup-steps.yml
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
|
|
16
|
+
copilot-setup-steps:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
# Set the permissions to the lowest permissions possible needed for your steps.
|
|
20
|
+
# Copilot will be given its own token for its operations.
|
|
21
|
+
permissions:
|
|
22
|
+
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
# You can define any steps you want, and they will run before the agent starts.
|
|
26
|
+
# If you do not check out your code, Copilot will do this for you.
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout code
|
|
29
|
+
uses: actions/checkout@v5
|
|
30
|
+
|
|
31
|
+
- name: Set up Python
|
|
32
|
+
uses: actions/setup-python@v6
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.11"
|
|
35
|
+
|
|
36
|
+
- name: Install uv
|
|
37
|
+
run: |
|
|
38
|
+
# Install uv using pip to avoid network restrictions
|
|
39
|
+
python -m pip install --upgrade pip
|
|
40
|
+
python -m pip install uv
|
|
41
|
+
|
|
42
|
+
- name: Create virtual environment and install dependencies
|
|
43
|
+
run: |
|
|
44
|
+
uv venv .venv
|
|
45
|
+
source .venv/bin/activate
|
|
46
|
+
uv pip install .[test] coverage
|
|
47
|
+
|
|
48
|
+
- name: Install development tools
|
|
49
|
+
run: |
|
|
50
|
+
uv tool install pre-commit
|
|
51
|
+
uv tool install pyright
|
|
52
|
+
|
|
53
|
+
- name: Set up pre-commit hooks
|
|
54
|
+
run: |
|
|
55
|
+
source .venv/bin/activate
|
|
56
|
+
pre-commit install --install-hooks
|
|
57
|
+
|
|
58
|
+
- name: Verify installation
|
|
59
|
+
run: |
|
|
60
|
+
source .venv/bin/activate
|
|
61
|
+
python --version
|
|
62
|
+
uv --version
|
|
63
|
+
pre-commit --version
|
|
64
|
+
pyright --version
|
|
65
|
+
python -c "import dpdispatcher; print('DPDispatcher installed successfully')"
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
on:
|
|
1
|
+
'on':
|
|
2
2
|
push:
|
|
3
|
+
branches-ignore:
|
|
4
|
+
- 'copilot/**'
|
|
5
|
+
- 'dependabot/**'
|
|
6
|
+
- 'pre-commit-ci-update-config'
|
|
3
7
|
pull_request:
|
|
4
8
|
name: Type checker
|
|
5
9
|
jobs:
|
|
@@ -8,11 +12,11 @@ jobs:
|
|
|
8
12
|
runs-on: ubuntu-latest
|
|
9
13
|
steps:
|
|
10
14
|
- uses: actions/checkout@v5
|
|
11
|
-
- uses: actions/setup-python@
|
|
15
|
+
- uses: actions/setup-python@v6
|
|
12
16
|
with:
|
|
13
17
|
python-version: '3.11'
|
|
14
18
|
- run: pip install uv
|
|
15
19
|
- run: uv pip install --system -e .[cloudserver,gui]
|
|
16
20
|
- uses: jakebailey/pyright-action@v2
|
|
17
21
|
with:
|
|
18
|
-
version: 1.1.
|
|
22
|
+
version: 1.1.404
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
on:
|
|
1
|
+
'on':
|
|
2
|
+
push:
|
|
3
|
+
branches-ignore:
|
|
4
|
+
- 'copilot/**'
|
|
5
|
+
- 'dependabot/**'
|
|
6
|
+
- 'pre-commit-ci-update-config'
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*'
|
|
9
|
+
pull_request:
|
|
2
10
|
name: Release to pypi
|
|
3
11
|
jobs:
|
|
4
12
|
release-to-pypi:
|
|
@@ -10,7 +18,7 @@ jobs:
|
|
|
10
18
|
steps:
|
|
11
19
|
- uses: actions/checkout@v5
|
|
12
20
|
- name: Setup python
|
|
13
|
-
uses: actions/setup-python@
|
|
21
|
+
uses: actions/setup-python@v6
|
|
14
22
|
with:
|
|
15
23
|
python-version: 3.x
|
|
16
24
|
architecture: x64
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
name: Test Bohrium
|
|
2
2
|
|
|
3
|
-
on:
|
|
3
|
+
'on':
|
|
4
4
|
push:
|
|
5
|
+
branches-ignore:
|
|
6
|
+
- 'copilot/**'
|
|
7
|
+
- 'dependabot/**'
|
|
8
|
+
- 'pre-commit-ci-update-config'
|
|
5
9
|
pull_request_target:
|
|
6
10
|
types:
|
|
7
11
|
- "labeled"
|
|
@@ -16,7 +20,7 @@ jobs:
|
|
|
16
20
|
with:
|
|
17
21
|
ref: "${{ github.event.pull_request.merge_commit_sha }}"
|
|
18
22
|
- name: Set up Python 3.12
|
|
19
|
-
uses: actions/setup-python@
|
|
23
|
+
uses: actions/setup-python@v6
|
|
20
24
|
with:
|
|
21
25
|
python-version: '3.12'
|
|
22
26
|
cache: 'pip'
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
name: Python package
|
|
2
2
|
|
|
3
|
-
on:
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
'on':
|
|
4
|
+
push:
|
|
5
|
+
branches-ignore:
|
|
6
|
+
- 'copilot/**'
|
|
7
|
+
- 'dependabot/**'
|
|
8
|
+
- 'pre-commit-ci-update-config'
|
|
9
|
+
pull_request:
|
|
6
10
|
|
|
7
11
|
jobs:
|
|
8
12
|
test:
|
|
@@ -24,11 +28,11 @@ jobs:
|
|
|
24
28
|
platform: macos-latest
|
|
25
29
|
include: # So run those legacy versions on Intel CPUs
|
|
26
30
|
- python-version: "3.7"
|
|
27
|
-
platform: macos-
|
|
31
|
+
platform: macos-15-intel
|
|
28
32
|
steps:
|
|
29
33
|
- uses: actions/checkout@v5
|
|
30
34
|
- name: Set up Python ${{ matrix.python-version }}
|
|
31
|
-
uses: actions/setup-python@
|
|
35
|
+
uses: actions/setup-python@v6
|
|
32
36
|
with:
|
|
33
37
|
python-version: ${{ matrix.python-version }}
|
|
34
38
|
- uses: astral-sh/setup-uv@v6
|
|
@@ -37,7 +37,7 @@ pydispatcher.egg-info
|
|
|
37
37
|
*/__pycache__
|
|
38
38
|
*.swp
|
|
39
39
|
.eggs
|
|
40
|
-
.coverage
|
|
40
|
+
.coverage*
|
|
41
41
|
dbconfig.json
|
|
42
42
|
.vscode/*
|
|
43
43
|
.idea
|
|
@@ -46,3 +46,17 @@ dbconfig.json
|
|
|
46
46
|
*.egg
|
|
47
47
|
*.egg-info
|
|
48
48
|
venv/*
|
|
49
|
+
node_modules/
|
|
50
|
+
# Test artifacts
|
|
51
|
+
*_flag_if_job_task_fail
|
|
52
|
+
*_job_id
|
|
53
|
+
*_job_tag_finished
|
|
54
|
+
*_task_tag_finished
|
|
55
|
+
*.sub
|
|
56
|
+
*.sub.run
|
|
57
|
+
script_*.py
|
|
58
|
+
# Job execution temporary files
|
|
59
|
+
err
|
|
60
|
+
log
|
|
61
|
+
# JSON files with hash names (job state files)
|
|
62
|
+
[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*.json
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# DPDispatcher Development Guide
|
|
2
|
+
|
|
3
|
+
DPDispatcher is a Python package used to generate HPC (High-Performance Computing) scheduler systems (Slurm/PBS/LSF/Bohrium) jobs input scripts, submit them to HPC systems, and poke until they finish.
|
|
4
|
+
|
|
5
|
+
Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
|
|
6
|
+
|
|
7
|
+
## Working Effectively
|
|
8
|
+
|
|
9
|
+
### Bootstrap, Build, and Test
|
|
10
|
+
|
|
11
|
+
- **Environment setup:** The Python environment, `uv`, `pre-commit`, and `pyright` are automatically set up by the Copilot environment. Simply activate the virtual environment:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
source .venv/bin/activate
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **Run the test suite:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m coverage run -p --source=./dpdispatcher -m unittest -v
|
|
21
|
+
python -m coverage combine
|
|
22
|
+
python -m coverage report
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **TIMING: Tests take ~25 seconds. NEVER CANCEL - set timeout to 2+ minutes.**
|
|
26
|
+
|
|
27
|
+
- **Run linting and formatting:**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pre-commit run --all-files
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- **TIMING: Linting takes <5 seconds.**
|
|
34
|
+
- **Fallback:** If pre-commit fails with network issues, use `ruff check . && ruff format --check .`
|
|
35
|
+
|
|
36
|
+
- **Run type checking:**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pyright
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- **TIMING: Type checking takes ~2-3 seconds.**
|
|
43
|
+
|
|
44
|
+
- **Build documentation:**
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv pip install .[docs]
|
|
48
|
+
cd doc
|
|
49
|
+
make html
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **TIMING: Documentation build takes ~14 seconds.**
|
|
53
|
+
|
|
54
|
+
### CLI Usage
|
|
55
|
+
|
|
56
|
+
- **Test basic CLI functionality:**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
dpdisp --help
|
|
60
|
+
dpdisp run examples/dpdisp_run.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- **Run sample job dispatch script:**
|
|
64
|
+
```bash
|
|
65
|
+
python examples/dpdisp_run.py
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Validation
|
|
69
|
+
|
|
70
|
+
- **ALWAYS run the test suite after making code changes.** Tests execute quickly (~25 seconds) and should never be cancelled.
|
|
71
|
+
- **ALWAYS run linting before committing:** `pre-commit run --all-files`
|
|
72
|
+
- **ALWAYS run type checking:** `pyright` to catch type-related issues.
|
|
73
|
+
- **Test CLI functionality:** Run `dpdisp --help` and test with example scripts to ensure the CLI works correctly.
|
|
74
|
+
- **Build documentation:** Run `make html` in the `doc/` directory to verify documentation builds without errors.
|
|
75
|
+
|
|
76
|
+
## Build and Development Workflow
|
|
77
|
+
|
|
78
|
+
- **Dependencies:** The project uses `uv` as the package manager for fast dependency resolution.
|
|
79
|
+
- **Build system:** Uses `setuptools` with `pyproject.toml` configuration.
|
|
80
|
+
- **Python versions:** Supports Python 3.7+ (check `pyproject.toml` for current support matrix).
|
|
81
|
+
- **Testing:** Uses `unittest` framework with coverage reporting.
|
|
82
|
+
- **Linting:** Uses `pre-commit` with `ruff` for linting and formatting, plus other quality checks.
|
|
83
|
+
- **Type checking:** Uses `pyright` for static type analysis (configured in `pyproject.toml`).
|
|
84
|
+
- **Documentation:** Uses Sphinx with MyST parser for markdown support.
|
|
85
|
+
|
|
86
|
+
## Key Components
|
|
87
|
+
|
|
88
|
+
### Core Modules
|
|
89
|
+
|
|
90
|
+
- **`dpdispatcher/submission.py`**: Main classes - `Submission`, `Job`, `Task`, `Resources`
|
|
91
|
+
- **`dpdispatcher/machine.py`**: Machine configuration and dispatch logic
|
|
92
|
+
- **`dpdispatcher/contexts/`**: Context managers for different execution environments (SSH, local, etc.)
|
|
93
|
+
- **`dpdispatcher/machines/`**: HPC scheduler implementations (Slurm, PBS, LSF, Shell, etc.)
|
|
94
|
+
|
|
95
|
+
### Configuration Files
|
|
96
|
+
|
|
97
|
+
- **`examples/machine/`**: Example machine configurations (JSON format)
|
|
98
|
+
- **`examples/resources/`**: Example resource specifications
|
|
99
|
+
- **`examples/task/`**: Example task definitions
|
|
100
|
+
- **`examples/dpdisp_run.py`**: Complete working example using PEP 723 script metadata
|
|
101
|
+
|
|
102
|
+
### Important Directories
|
|
103
|
+
|
|
104
|
+
- **`tests/`**: Comprehensive test suite including unit tests and integration tests
|
|
105
|
+
- **`doc/`**: Sphinx documentation source files
|
|
106
|
+
- **`ci/`**: CI/CD configuration for Docker-based testing
|
|
107
|
+
|
|
108
|
+
## Common Tasks
|
|
109
|
+
|
|
110
|
+
### Running Examples
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Example with lazy local execution (no HPC needed)
|
|
114
|
+
dpdisp run examples/dpdisp_run.py
|
|
115
|
+
|
|
116
|
+
# Example output files created:
|
|
117
|
+
# - log: contains "hello world!" output
|
|
118
|
+
# - Various job tracking files (automatically cleaned up)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Testing with Different HPC Systems
|
|
122
|
+
|
|
123
|
+
- **Local/Shell execution:** Use `LazyLocalContext` with `Shell` batch type (examples/machine/lazy_local.json)
|
|
124
|
+
- **SSH remote execution:** Use `SSHContext` (requires SSH setup)
|
|
125
|
+
- **HPC schedulers:** Use `Slurm`, `PBS`, `LSF` batch types (require actual HPC environment)
|
|
126
|
+
|
|
127
|
+
### Debugging Job Execution
|
|
128
|
+
|
|
129
|
+
- Check job logs in the work directory
|
|
130
|
+
- Use `dpdisp submission` commands to inspect job states
|
|
131
|
+
- Review machine and resource configurations in JSON files
|
|
132
|
+
|
|
133
|
+
## Project Structure Reference
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
.
|
|
137
|
+
├── README.md
|
|
138
|
+
├── pyproject.toml # Project configuration and dependencies
|
|
139
|
+
├── dpdispatcher/ # Main package
|
|
140
|
+
│ ├── __init__.py
|
|
141
|
+
│ ├── submission.py # Core submission/job/task classes
|
|
142
|
+
│ ├── machine.py # Machine configuration
|
|
143
|
+
│ ├── contexts/ # Execution contexts (SSH, local, etc.)
|
|
144
|
+
│ ├── machines/ # HPC scheduler implementations
|
|
145
|
+
│ └── utils/ # Utility functions
|
|
146
|
+
├── examples/ # Example configurations and scripts
|
|
147
|
+
│ ├── machine/ # Example machine configs
|
|
148
|
+
│ ├── resources/ # Example resource specs
|
|
149
|
+
│ ├── task/ # Example task definitions
|
|
150
|
+
│ └── dpdisp_run.py # Complete working example
|
|
151
|
+
├── tests/ # Comprehensive test suite
|
|
152
|
+
├── doc/ # Sphinx documentation
|
|
153
|
+
└── ci/ # CI/CD Docker configurations
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Development Notes
|
|
157
|
+
|
|
158
|
+
- **Virtual environment is pre-configured** - The environment is automatically set up; simply activate with `source .venv/bin/activate`
|
|
159
|
+
- **Always add type hints** - Include proper type annotations in all Python code for better maintainability
|
|
160
|
+
- **Always use conventional commit format** - All commit messages and PR titles must follow the conventional commit specification (e.g., `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`)
|
|
161
|
+
- **Test artifacts are gitignored** - Job execution creates temporary files that are automatically excluded
|
|
162
|
+
- **Pre-commit hooks are ready** - Pre-commit is pre-installed and hooks are configured
|
|
163
|
+
- **Multiple execution contexts** - Code supports local execution, SSH remote execution, and various HPC schedulers
|
|
164
|
+
- **Extensive examples** - Use `examples/` directory as reference for proper configuration formats
|
|
165
|
+
|
|
166
|
+
## Troubleshooting
|
|
167
|
+
|
|
168
|
+
- **Virtual environment issues:** The virtual environment is pre-created; simply activate with `source .venv/bin/activate`
|
|
169
|
+
- **Development tools:** `pre-commit` and `pyright` are pre-installed and ready to use
|
|
170
|
+
- **Test failures:** Most tests run locally; some require specific HPC environments and will be skipped
|
|
171
|
+
- **Documentation build warnings:** Some warnings about external inventory URLs are expected in sandboxed environments
|
|
172
|
+
- **Pre-commit network issues:** If pre-commit fails with network timeouts, run `ruff check` and `ruff format` directly
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dpdispatcher
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.12
|
|
4
4
|
Summary: Generate HPC scheduler systems jobs input scripts, submit these scripts to HPC systems, and poke until they finish
|
|
5
5
|
Author: DeepModeling
|
|
6
6
|
License: GNU LESSER GENERAL PUBLIC LICENSE
|
|
@@ -12,6 +12,17 @@ services:
|
|
|
12
12
|
- "22"
|
|
13
13
|
volumes:
|
|
14
14
|
- ssh_config:/root/.ssh
|
|
15
|
+
jumphost:
|
|
16
|
+
image: takeyamajp/ubuntu-sshd:ubuntu22.04
|
|
17
|
+
build: .
|
|
18
|
+
container_name: jumphost
|
|
19
|
+
hostname: jumphost
|
|
20
|
+
environment:
|
|
21
|
+
ROOT_PASSWORD: dpdispatcher
|
|
22
|
+
expose:
|
|
23
|
+
- "22"
|
|
24
|
+
volumes:
|
|
25
|
+
- ssh_config:/root/.ssh
|
|
15
26
|
test:
|
|
16
27
|
image: python:3.10
|
|
17
28
|
tty: true
|
|
@@ -25,6 +36,7 @@ services:
|
|
|
25
36
|
- ../..:/dpdispatcher
|
|
26
37
|
depends_on:
|
|
27
38
|
- server
|
|
39
|
+
- jumphost
|
|
28
40
|
|
|
29
41
|
volumes:
|
|
30
42
|
ssh_config:
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
docker compose up -d --no-build
|
|
4
|
+
|
|
5
|
+
# Set up SSH keys on server
|
|
6
|
+
docker exec server /bin/bash -c "ssh-keygen -b 2048 -t rsa -f /root/.ssh/id_rsa -q -N \"\" && cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys"
|
|
7
|
+
docker exec server /bin/bash -c "mkdir -p /dpdispatcher_working"
|
|
8
|
+
docker exec server /bin/bash -c "mkdir -p /tmp/rsync_test"
|
|
9
|
+
|
|
10
|
+
# Set up SSH keys on jumphost and configure it to access server
|
|
11
|
+
docker exec jumphost /bin/bash -c "ssh-keygen -b 2048 -t rsa -f /root/.ssh/id_rsa -q -N \"\" && cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys"
|
|
12
|
+
|
|
13
|
+
# Copy keys between containers to enable jump host functionality
|
|
14
|
+
# Get the public key from jumphost and add it to server's authorized_keys
|
|
15
|
+
docker exec jumphost /bin/bash -c "cat /root/.ssh/id_rsa.pub" | docker exec -i server /bin/bash -c "cat >> /root/.ssh/authorized_keys"
|
|
16
|
+
|
|
17
|
+
# Get the public key from test (which shares volume with server) and add it to jumphost authorized_keys
|
|
18
|
+
docker exec test /bin/bash -c "cat /root/.ssh/id_rsa.pub" | docker exec -i jumphost /bin/bash -c "cat >> /root/.ssh/authorized_keys"
|
|
19
|
+
|
|
20
|
+
# Configure SSH client settings for known hosts to avoid host key verification
|
|
21
|
+
docker exec test /bin/bash -c "echo 'StrictHostKeyChecking no' >> /root/.ssh/config && echo 'UserKnownHostsFile /dev/null' >> /root/.ssh/config"
|
|
22
|
+
docker exec jumphost /bin/bash -c "echo 'StrictHostKeyChecking no' >> /root/.ssh/config && echo 'UserKnownHostsFile /dev/null' >> /root/.ssh/config"
|
|
23
|
+
docker exec server /bin/bash -c "echo 'StrictHostKeyChecking no' >> /root/.ssh/config && echo 'UserKnownHostsFile /dev/null' >> /root/.ssh/config"
|
|
24
|
+
|
|
25
|
+
# Install rsync on all containers
|
|
26
|
+
docker exec test /bin/bash -c "apt-get -y update && apt-get -y install rsync"
|
|
27
|
+
docker exec jumphost /bin/bash -c "apt-get -y update && apt-get -y install rsync"
|
|
28
|
+
docker exec server /bin/bash -c "apt-get -y update && apt-get -y install rsync"
|
|
@@ -33,6 +33,28 @@ It's suggested to generate [SSH keys](https://help.ubuntu.com/community/SSH/Open
|
|
|
33
33
|
|
|
34
34
|
Note that `SSH` context is [non-login](https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html), so `bash_profile` files will not be executed outside the submission script.
|
|
35
35
|
|
|
36
|
+
### SSH Jump Host (Bastion Server)
|
|
37
|
+
|
|
38
|
+
For connecting to internal servers through a jump host (bastion server), SSH context supports jump host configuration. This allows connecting to internal servers that are not directly accessible from the internet.
|
|
39
|
+
|
|
40
|
+
Specify the ProxyCommand directly using {dargs:argument}`proxy_command <machine[SSHContext]/remote_profile/proxy_command>`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"context_type": "SSHContext",
|
|
45
|
+
"remote_profile": {
|
|
46
|
+
"hostname": "internal-server.company.com",
|
|
47
|
+
"username": "user",
|
|
48
|
+
"key_filename": "/path/to/internal_key",
|
|
49
|
+
"proxy_command": "ssh -W internal-server.company.com:22 -i /path/to/jump_key jumpuser@bastion.company.com"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Note**: Unlike OpenSSH, Paramiko's ProxyCommand requires explicit hostname and port instead of `%h:%p` placeholders. The proxy command must specify the actual target hostname and port that matches the `hostname` and `port` in the remote profile.
|
|
55
|
+
|
|
56
|
+
This configuration establishes the connection path: Local → Jump Host → Target Server.
|
|
57
|
+
|
|
36
58
|
## Bohrium
|
|
37
59
|
|
|
38
60
|
{dargs:argument}`context_type <machine/context_type>`: `Bohrium`
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.6.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 6,
|
|
31
|
+
__version__ = version = '0.6.12'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 12)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gfd51e420a'
|
{dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/dp_cloud_server_context.py
RENAMED
|
@@ -161,7 +161,9 @@ class BohriumContext(BaseContext):
|
|
|
161
161
|
# return oss_task_zip
|
|
162
162
|
# api.upload(self.oss_task_dir, zip_task_file)
|
|
163
163
|
|
|
164
|
-
def download(
|
|
164
|
+
def download(
|
|
165
|
+
self, submission, check_exists=False, mark_failure=True, back_error=False
|
|
166
|
+
):
|
|
165
167
|
jobs = submission.belonging_jobs
|
|
166
168
|
job_hashs = {}
|
|
167
169
|
job_infos = {}
|
|
@@ -83,7 +83,7 @@ class LazyLocalContext(BaseContext):
|
|
|
83
83
|
|
|
84
84
|
def upload(
|
|
85
85
|
self,
|
|
86
|
-
|
|
86
|
+
submission,
|
|
87
87
|
# local_up_files,
|
|
88
88
|
dereference=True,
|
|
89
89
|
):
|
|
@@ -91,7 +91,7 @@ class LazyLocalContext(BaseContext):
|
|
|
91
91
|
|
|
92
92
|
def download(
|
|
93
93
|
self,
|
|
94
|
-
|
|
94
|
+
submission,
|
|
95
95
|
# remote_down_files,
|
|
96
96
|
check_exists=False,
|
|
97
97
|
mark_failure=True,
|
|
@@ -95,11 +95,11 @@ class OpenAPIContext(BaseContext):
|
|
|
95
95
|
raise ValueError(
|
|
96
96
|
"remote_profile must contain 'project_id' or set environment variable 'BOHRIUM_PROJECT_ID'"
|
|
97
97
|
)
|
|
98
|
-
self.client = Bohrium(
|
|
98
|
+
self.client = Bohrium( # type: ignore[reportPossiblyUnboundVariable]
|
|
99
99
|
access_key=access_key, project_id=project_id, app_key=app_key
|
|
100
100
|
)
|
|
101
|
-
self.storage = Tiefblue()
|
|
102
|
-
self.job = Job(client=self.client)
|
|
101
|
+
self.storage = Tiefblue() # type: ignore[reportPossiblyUnboundVariable]
|
|
102
|
+
self.job = Job(client=self.client) # type: ignore[reportPossiblyUnboundVariable]
|
|
103
103
|
self.jgid = None
|
|
104
104
|
os.makedirs(DP_CLOUD_SERVER_HOME_DIR, exist_ok=True)
|
|
105
105
|
|
|
@@ -206,7 +206,9 @@ class OpenAPIContext(BaseContext):
|
|
|
206
206
|
# return oss_task_zip
|
|
207
207
|
# api.upload(self.oss_task_dir, zip_task_file)
|
|
208
208
|
|
|
209
|
-
def download(
|
|
209
|
+
def download(
|
|
210
|
+
self, submission, check_exists=False, mark_failure=True, back_error=False
|
|
211
|
+
):
|
|
210
212
|
jobs = submission.belonging_jobs
|
|
211
213
|
job_hashs = {}
|
|
212
214
|
job_infos = {}
|
|
@@ -45,6 +45,7 @@ class SSHSession:
|
|
|
45
45
|
tar_compress=True,
|
|
46
46
|
look_for_keys=True,
|
|
47
47
|
execute_command=None,
|
|
48
|
+
proxy_command=None,
|
|
48
49
|
):
|
|
49
50
|
self.hostname = hostname
|
|
50
51
|
self.username = username
|
|
@@ -58,6 +59,7 @@ class SSHSession:
|
|
|
58
59
|
self.tar_compress = tar_compress
|
|
59
60
|
self.look_for_keys = look_for_keys
|
|
60
61
|
self.execute_command = execute_command
|
|
62
|
+
self.proxy_command = proxy_command
|
|
61
63
|
self._keyboard_interactive_auth = False
|
|
62
64
|
self._setup_ssh()
|
|
63
65
|
|
|
@@ -142,7 +144,12 @@ class SSHSession:
|
|
|
142
144
|
# transport = self.ssh.get_transport()
|
|
143
145
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
144
146
|
sock.settimeout(self.timeout)
|
|
145
|
-
|
|
147
|
+
|
|
148
|
+
# Use ProxyCommand if configured (either directly or via jump host parameters)
|
|
149
|
+
if self.proxy_command is not None:
|
|
150
|
+
sock = paramiko.ProxyCommand(self.proxy_command)
|
|
151
|
+
else:
|
|
152
|
+
sock.connect((self.hostname, self.port))
|
|
146
153
|
|
|
147
154
|
# Make a Paramiko Transport object using the socket
|
|
148
155
|
ts = paramiko.Transport(sock)
|
|
@@ -340,6 +347,9 @@ class SSHSession:
|
|
|
340
347
|
"enable searching for discoverable private key files in ~/.ssh/"
|
|
341
348
|
)
|
|
342
349
|
doc_execute_command = "execute command after ssh connection is established."
|
|
350
|
+
doc_proxy_command = (
|
|
351
|
+
"ProxyCommand to use for SSH connection through intermediate servers."
|
|
352
|
+
)
|
|
343
353
|
ssh_remote_profile_args = [
|
|
344
354
|
Argument("hostname", str, optional=False, doc=doc_hostname),
|
|
345
355
|
Argument("username", str, optional=False, doc=doc_username),
|
|
@@ -388,6 +398,13 @@ class SSHSession:
|
|
|
388
398
|
default=None,
|
|
389
399
|
doc=doc_execute_command,
|
|
390
400
|
),
|
|
401
|
+
Argument(
|
|
402
|
+
"proxy_command",
|
|
403
|
+
[str, type(None)],
|
|
404
|
+
optional=True,
|
|
405
|
+
default=None,
|
|
406
|
+
doc=doc_proxy_command,
|
|
407
|
+
),
|
|
391
408
|
]
|
|
392
409
|
ssh_remote_profile_format = Argument(
|
|
393
410
|
"ssh_session", dict, ssh_remote_profile_args
|
|
@@ -396,23 +413,37 @@ class SSHSession:
|
|
|
396
413
|
|
|
397
414
|
def put(self, from_f, to_f):
|
|
398
415
|
if self.rsync_available:
|
|
416
|
+
# For rsync, we need to use %h:%p placeholders for target host/port
|
|
417
|
+
proxy_cmd_rsync = None
|
|
418
|
+
if self.proxy_command is not None:
|
|
419
|
+
proxy_cmd_rsync = self.proxy_command.replace(
|
|
420
|
+
f"{self.hostname}:{self.port}", "%h:%p"
|
|
421
|
+
)
|
|
399
422
|
return rsync(
|
|
400
423
|
from_f,
|
|
401
424
|
self.remote + ":" + to_f,
|
|
402
425
|
port=self.port,
|
|
403
426
|
key_filename=self.key_filename,
|
|
404
427
|
timeout=self.timeout,
|
|
428
|
+
proxy_command=proxy_cmd_rsync,
|
|
405
429
|
)
|
|
406
430
|
return self.sftp.put(from_f, to_f)
|
|
407
431
|
|
|
408
432
|
def get(self, from_f, to_f):
|
|
409
433
|
if self.rsync_available:
|
|
434
|
+
# For rsync, we need to use %h:%p placeholders for target host/port
|
|
435
|
+
proxy_cmd_rsync = None
|
|
436
|
+
if self.proxy_command is not None:
|
|
437
|
+
proxy_cmd_rsync = self.proxy_command.replace(
|
|
438
|
+
f"{self.hostname}:{self.port}", "%h:%p"
|
|
439
|
+
)
|
|
410
440
|
return rsync(
|
|
411
441
|
self.remote + ":" + from_f,
|
|
412
442
|
to_f,
|
|
413
443
|
port=self.port,
|
|
414
444
|
key_filename=self.key_filename,
|
|
415
445
|
timeout=self.timeout,
|
|
446
|
+
proxy_command=proxy_cmd_rsync,
|
|
416
447
|
)
|
|
417
448
|
return self.sftp.get(from_f, to_f)
|
|
418
449
|
|
|
@@ -825,8 +856,8 @@ class SSHContext(BaseContext):
|
|
|
825
856
|
# print(pid)
|
|
826
857
|
return {"stdin": stdin, "stdout": stdout, "stderr": stderr}
|
|
827
858
|
|
|
828
|
-
def check_finish(self,
|
|
829
|
-
return
|
|
859
|
+
def check_finish(self, proc):
|
|
860
|
+
return proc["stdout"].channel.exit_status_ready()
|
|
830
861
|
|
|
831
862
|
def get_return(self, cmd_pipes):
|
|
832
863
|
if not self.check_finish(cmd_pipes):
|
|
@@ -888,11 +919,11 @@ class SSHContext(BaseContext):
|
|
|
888
919
|
# local tar
|
|
889
920
|
if os.path.isfile(os.path.join(self.local_root, of)):
|
|
890
921
|
os.remove(os.path.join(self.local_root, of))
|
|
891
|
-
with tarfile.open(
|
|
922
|
+
with tarfile.open( # type: ignore[reportCallIssue, reportArgumentType]
|
|
892
923
|
os.path.join(self.local_root, of),
|
|
893
|
-
tarfile_mode,
|
|
894
|
-
dereference=dereference,
|
|
895
|
-
**kwargs,
|
|
924
|
+
mode=tarfile_mode, # type: ignore[reportArgumentType]
|
|
925
|
+
dereference=dereference, # type: ignore[reportArgumentType]
|
|
926
|
+
**kwargs, # type: ignore[reportArgumentType]
|
|
896
927
|
) as tar:
|
|
897
928
|
# avoid compressing duplicated files or directories
|
|
898
929
|
for ii in set(files):
|
|
@@ -227,7 +227,7 @@ class Machine(metaclass=ABCMeta):
|
|
|
227
227
|
return if_recover
|
|
228
228
|
|
|
229
229
|
@abstractmethod
|
|
230
|
-
def check_finish_tag(self,
|
|
230
|
+
def check_finish_tag(self, job):
|
|
231
231
|
raise NotImplementedError(
|
|
232
232
|
"abstract method check_finish_tag should be implemented by derived class"
|
|
233
233
|
)
|