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.

Files changed (265) hide show
  1. dpdispatcher-0.6.12/.github/workflows/copilot-setup-steps.yml +65 -0
  2. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/machines.yml +7 -3
  3. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/pyright.yml +7 -3
  4. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/release.yml +10 -2
  5. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/test-bohrium.yml +6 -2
  6. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/test.yml +9 -5
  7. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.gitignore +15 -1
  8. dpdispatcher-0.6.12/AGENTS.md +172 -0
  9. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/PKG-INFO +1 -1
  10. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh/docker-compose.yml +12 -0
  11. dpdispatcher-0.6.12/ci/ssh/start-ssh.sh +28 -0
  12. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/context.md +22 -0
  13. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/_version.py +3 -3
  14. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/dp_cloud_server_context.py +3 -1
  15. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/lazy_local_context.py +2 -2
  16. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/openapi_context.py +6 -4
  17. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/ssh_context.py +38 -7
  18. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machine.py +1 -1
  19. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/JH_UniScheduler.py +0 -3
  20. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/fugaku.py +0 -3
  21. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/lsf.py +0 -3
  22. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/openapi.py +3 -3
  23. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/pbs.py +0 -6
  24. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/shell.py +0 -3
  25. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/slurm.py +0 -3
  26. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/client.py +5 -5
  27. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/utils.py +20 -6
  28. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/PKG-INFO +1 -1
  29. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/SOURCES.txt +6 -0
  30. dpdispatcher-0.6.12/examples/machine/ssh_proxy_command.json +13 -0
  31. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/pyproject.toml +2 -3
  32. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_examples.py +1 -0
  33. dpdispatcher-0.6.12/tests/test_rsync_flags.py +87 -0
  34. dpdispatcher-0.6.12/tests/test_rsync_proxy.py +130 -0
  35. dpdispatcher-0.6.12/tests/test_ssh_jump_host.py +90 -0
  36. dpdispatcher-0.6.11/ci/ssh/start-ssh.sh +0 -6
  37. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.git_archival.txt +0 -0
  38. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.gitattributes +0 -0
  39. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/dependabot.yml +0 -0
  40. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/ci-docker.yml +0 -0
  41. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/mirror_gitee.yml +0 -0
  42. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.github/workflows/publish_conda.yml +0 -0
  43. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.pre-commit-config.yaml +0 -0
  44. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/.readthedocs.yaml +0 -0
  45. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/CONTRIBUTING.md +0 -0
  46. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/Dockerfile +0 -0
  47. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/LICENSE +0 -0
  48. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/README.md +0 -0
  49. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/LICENSE +0 -0
  50. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/README.md +0 -0
  51. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs/docker-compose.yml +0 -0
  52. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs/start-pbs.sh +0 -0
  53. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/pbs.sh +0 -0
  54. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/docker-compose.yml +0 -0
  55. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/register_cluster.sh +0 -0
  56. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm/start-slurm.sh +0 -0
  57. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/slurm.sh +0 -0
  58. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh.sh +0 -0
  59. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/ci/ssh_rsync.sh +0 -0
  60. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/codecov.yml +0 -0
  61. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/conda/conda_build_config.yaml +0 -0
  62. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/conda/meta.yaml +0 -0
  63. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/.gitignore +0 -0
  64. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/Makefile +0 -0
  65. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/batch.md +0 -0
  66. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/cli.rst +0 -0
  67. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/conf.py +0 -0
  68. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/credits.rst +0 -0
  69. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/dpdispatcher_on_yarn.md +0 -0
  70. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/env.md +0 -0
  71. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/expanse.md +0 -0
  72. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/g16.md +0 -0
  73. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/shell.md +0 -0
  74. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/examples/template.md +0 -0
  75. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/getting-started.md +0 -0
  76. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/index.rst +0 -0
  77. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/install.md +0 -0
  78. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/machine.rst +0 -0
  79. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/make.bat +0 -0
  80. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/pep723.rst +0 -0
  81. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/requirements.txt +0 -0
  82. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/resources.rst +0 -0
  83. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/run.md +0 -0
  84. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/doc/task.rst +0 -0
  85. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/__init__.py +0 -0
  86. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/__main__.py +0 -0
  87. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/arginfo.py +0 -0
  88. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/base_context.py +0 -0
  89. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/__init__.py +0 -0
  90. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/hdfs_context.py +0 -0
  91. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/contexts/local_context.py +0 -0
  92. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dlog.py +0 -0
  93. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpcloudserver/__init__.py +0 -0
  94. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpcloudserver/client.py +0 -0
  95. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/dpdisp.py +0 -0
  96. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/__init__.py +0 -0
  97. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/gui.py +0 -0
  98. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/run.py +0 -0
  99. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/entrypoints/submission.py +0 -0
  100. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/__init__.py +0 -0
  101. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/distributed_shell.py +0 -0
  102. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/machines/dp_cloud_server.py +0 -0
  103. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/run.py +0 -0
  104. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/submission.py +0 -0
  105. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/__init__.py +0 -0
  106. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/__init__.py +0 -0
  107. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/config.py +0 -0
  108. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/retcode.py +0 -0
  109. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/dpcloudserver/zip_file.py +0 -0
  110. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/hdfs_cli.py +0 -0
  111. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/job_status.py +0 -0
  112. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher/utils/record.py +0 -0
  113. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/dependency_links.txt +0 -0
  114. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/entry_points.txt +0 -0
  115. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/requires.txt +0 -0
  116. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/dpdispatcher.egg-info/top_level.txt +0 -0
  117. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/dpdisp_run.py +0 -0
  118. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/expanse.json +0 -0
  119. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/lazy_local.json +0 -0
  120. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/machine/mandu.json +0 -0
  121. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/expanse_cpu.json +0 -0
  122. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/mandu.json +0 -0
  123. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/template.slurm +0 -0
  124. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/resources/tiger.json +0 -0
  125. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/task/deepmd-kit.json +0 -0
  126. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/examples/task/g16.json +0 -0
  127. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/scripts/script_gen_dargs_docs.py +0 -0
  128. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/scripts/script_gen_dargs_json.py +0 -0
  129. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/setup.cfg +0 -0
  130. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/.gitignore +0 -0
  131. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/__init__.py +0 -0
  132. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/batch.json +0 -0
  133. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/context.py +0 -0
  134. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/debug_test_class_submission_init.py +0 -0
  135. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_JH_UniScheduler.py +0 -0
  136. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_ali_ehpc.py +0 -0
  137. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_dp_cloud_server.py +0 -0
  138. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_lazy_ali_ehpc.py +0 -0
  139. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_lsf.py +0 -0
  140. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_shell.py +0 -0
  141. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_slurm.py +0 -0
  142. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/devel_test_ssh_ali_ehpc.py +0 -0
  143. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/graph.pb +0 -0
  144. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/hello_world.py +0 -0
  145. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/job.json +0 -0
  146. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine.json +0 -0
  147. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_JH_UniScheduler.json +0 -0
  148. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_ali_ehpc.json +0 -0
  149. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_center.json +0 -0
  150. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_diffenert.json +0 -0
  151. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_dp_cloud_server.json +0 -0
  152. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_fugaku.json +0 -0
  153. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_if_cuda_multi_devices.json +0 -0
  154. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_jh_unischeduler.json +0 -0
  155. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_lsf.json +0 -0
  156. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazy_local_slurm.json +0 -0
  157. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lazylocal_shell.json +0 -0
  158. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_local_fugaku.json +0 -0
  159. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_local_shell.json +0 -0
  160. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_lsf.json +0 -0
  161. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_openapi.json +0 -0
  162. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_slurm.json +0 -0
  163. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/machine_yarn.json +0 -0
  164. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/resources.json +0 -0
  165. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/submission.json +0 -0
  166. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/jsons/task.json +0 -0
  167. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/sample_class.py +0 -0
  168. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/script_gen_json.py +0 -0
  169. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/slurm_test.env +0 -0
  170. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_JH_UniScheduler_script_generation.py +0 -0
  171. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_argcheck.py +0 -0
  172. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_job.py +0 -0
  173. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_machine.py +0 -0
  174. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_machine_dispatch.py +0 -0
  175. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_resources.py +0 -0
  176. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_submission.py +0 -0
  177. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_submission_init.py +0 -0
  178. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_class_task.py +0 -0
  179. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_cli.py +0 -0
  180. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/conf.lmp +0 -0
  181. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/input.lammps +0 -0
  182. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-1/some_dir/some_file +0 -0
  183. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-2/conf.lmp +0 -0
  184. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-2/input.lammps +0 -0
  185. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-3/conf.lmp +0 -0
  186. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-3/input.lammps +0 -0
  187. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-4/conf.lmp +0 -0
  188. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/bct-4/input.lammps +0 -0
  189. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/dir with space/file with space +0 -0
  190. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/graph.pb +0 -0
  191. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_context_dir/0_md/some_dir/some_file +0 -0
  192. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_group_size.py +0 -0
  193. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_gui.py +0 -0
  194. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_context.py +0 -0
  195. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-1/conf.lmp +0 -0
  196. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-1/input.lammps +0 -0
  197. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-2/conf.lmp +0 -0
  198. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-2/input.lammps +0 -0
  199. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-3/conf.lmp +0 -0
  200. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-3/input.lammps +0 -0
  201. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-4/conf.lmp +0 -0
  202. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/bct-4/input.lammps +0 -0
  203. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_hdfs_dir/0_md/graph.pb +0 -0
  204. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_if_cuda_multi_devices/test_dir/test.txt +0 -0
  205. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_import_classes.py +0 -0
  206. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-1/conf.lmp +0 -0
  207. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-1/input.lammps +0 -0
  208. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-2/conf.lmp +0 -0
  209. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-2/input.lammps +0 -0
  210. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-3/conf.lmp +0 -0
  211. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-3/input.lammps +0 -0
  212. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-4/conf.lmp +0 -0
  213. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/bct-4/input.lammps +0 -0
  214. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_jh_unischeduler/0_md/graph.pb +0 -0
  215. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lazy_local_context.py +0 -0
  216. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_local_context.py +0 -0
  217. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-1/conf.lmp +0 -0
  218. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-1/input.lammps +0 -0
  219. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-2/conf.lmp +0 -0
  220. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-2/input.lammps +0 -0
  221. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-3/conf.lmp +0 -0
  222. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-3/input.lammps +0 -0
  223. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-4/conf.lmp +0 -0
  224. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/bct-4/input.lammps +0 -0
  225. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/graph.pb +0 -0
  226. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_dir/0_md/submission.json +0 -0
  227. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_lsf_script_generation.py +0 -0
  228. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-1/conf.lmp +0 -0
  229. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-1/input.lammps +0 -0
  230. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-2/conf.lmp +0 -0
  231. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-2/input.lammps +0 -0
  232. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-3/conf.lmp +0 -0
  233. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-3/input.lammps +0 -0
  234. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-4/conf.lmp +0 -0
  235. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/bct-4/input.lammps +0 -0
  236. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_pbs_dir/0_md/graph.pb +0 -0
  237. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_retry.py +0 -0
  238. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run.py +0 -0
  239. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission.py +0 -0
  240. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission_bohrium.py +0 -0
  241. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_run_submission_ratio_unfinished.py +0 -0
  242. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_cuda_multi_devices.py +0 -0
  243. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival.py +0 -0
  244. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/fail_dir/mock_fail_task.txt +0 -0
  245. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir with space/example.txt +0 -0
  246. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir1/example.txt +0 -0
  247. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir2/example.txt +0 -0
  248. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir3/example.txt +0 -0
  249. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/dir4/example.txt +0 -0
  250. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/parent_dir/graph.pb +0 -0
  251. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_shell_trival_dir/recover_dir/mock_recover_task.txt +0 -0
  252. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-1/conf.lmp +0 -0
  253. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-1/input.lammps +0 -0
  254. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-2/conf.lmp +0 -0
  255. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-2/input.lammps +0 -0
  256. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-3/conf.lmp +0 -0
  257. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-3/input.lammps +0 -0
  258. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-4/conf.lmp +0 -0
  259. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/bct-4/input.lammps +0 -0
  260. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/d3c842c5b9476e48f7145b370cd330372b9293e1.json +0 -0
  261. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/graph.pb +0 -0
  262. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_dir/0_md/submission.json +0 -0
  263. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_slurm_script_generation.py +0 -0
  264. {dpdispatcher-0.6.11 → dpdispatcher-0.6.12}/tests/test_ssh_context.py +0 -0
  265. {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,8 +1,12 @@
1
1
  name: Test on different machines
2
2
 
3
- on:
4
- - push
5
- - pull_request
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
  build:
@@ -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@v5
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.308
22
+ version: 1.1.404
@@ -1,4 +1,12 @@
1
- on: [push, pull_request]
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@v5
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@v5
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
- - push
5
- - pull_request
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-13
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@v5
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.11
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.11'
32
- __version_tuple__ = version_tuple = (0, 6, 11)
31
+ __version__ = version = '0.6.12'
32
+ __version_tuple__ = version_tuple = (0, 6, 12)
33
33
 
34
- __commit_id__ = commit_id = 'gce67803b9'
34
+ __commit_id__ = commit_id = 'gfd51e420a'
@@ -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(self, submission):
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
- jobs,
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
- jobs,
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(self, submission):
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
- sock.connect((self.hostname, self.port))
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, cmd_pipes):
829
- return cmd_pipes["stdout"].channel.exit_status_ready()
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, **kwargs):
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
  )