experimaestro 1.7.0rc1__tar.gz → 1.7.0rc3__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 experimaestro might be problematic. Click here for more details.

Files changed (153) hide show
  1. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/PKG-INFO +1 -1
  2. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/pyproject.toml +2 -2
  3. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/commandline.py +3 -7
  4. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/connectors/__init__.py +5 -2
  5. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/connectors/local.py +9 -5
  6. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/connectors/ssh.py +1 -1
  7. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/experiments/cli.py +7 -3
  8. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launcherfinder/registry.py +5 -1
  9. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launchers/slurm/base.py +47 -9
  10. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/base.py +4 -0
  11. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/dynamic_outputs.py +1 -1
  12. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scriptbuilder.py +3 -1
  13. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/sphinx/__init__.py +6 -13
  14. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/bin/sbatch +16 -2
  15. experimaestro-1.7.0rc3/src/experimaestro/tests/launchers/bin/srun +5 -0
  16. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/common.py +5 -1
  17. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/LICENSE +0 -0
  18. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/README.md +0 -0
  19. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/__init__.py +0 -0
  20. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/__main__.py +0 -0
  21. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/annotations.py +0 -0
  22. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/checkers.py +0 -0
  23. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/cli/__init__.py +0 -0
  24. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/cli/filter.py +0 -0
  25. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/cli/jobs.py +0 -0
  26. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/click.py +0 -0
  27. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/compat.py +0 -0
  28. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/__init__.py +0 -0
  29. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/arguments.py +0 -0
  30. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/context.py +0 -0
  31. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/objects.py +0 -0
  32. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/objects.pyi +0 -0
  33. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/serialization.py +0 -0
  34. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/serializers.py +0 -0
  35. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/types.py +0 -0
  36. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/core/utils.py +0 -0
  37. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/exceptions.py +0 -0
  38. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/experiments/__init__.py +0 -0
  39. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/experiments/configuration.py +0 -0
  40. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/generators.py +0 -0
  41. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/huggingface.py +0 -0
  42. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/ipc.py +0 -0
  43. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launcherfinder/__init__.py +0 -0
  44. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launcherfinder/base.py +0 -0
  45. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launcherfinder/parser.py +0 -0
  46. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launcherfinder/specs.py +0 -0
  47. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launchers/__init__.py +0 -0
  48. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launchers/direct.py +0 -0
  49. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launchers/oar.py +0 -0
  50. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/launchers/slurm/__init__.py +0 -0
  51. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/locking.py +0 -0
  52. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mkdocs/__init__.py +0 -0
  53. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mkdocs/annotations.py +0 -0
  54. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mkdocs/base.py +0 -0
  55. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mkdocs/metaloader.py +0 -0
  56. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mkdocs/style.css +0 -0
  57. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/mypy.py +0 -0
  58. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/notifications.py +0 -0
  59. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/py.typed +0 -0
  60. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/rpyc.py +0 -0
  61. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/run.py +0 -0
  62. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/__init__.py +0 -0
  63. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/dependencies.py +0 -0
  64. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/services.py +0 -0
  65. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/scheduler/workspace.py +0 -0
  66. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/__init__.py +0 -0
  67. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/016b4a6cdced82ab3aa1.ttf +0 -0
  68. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
  69. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
  70. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
  71. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
  72. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
  73. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
  74. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
  75. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
  76. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
  77. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/50701fbb8177c2dde530.ttf +0 -0
  78. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
  79. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
  80. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/878f31251d960bd6266f.woff2 +0 -0
  81. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
  82. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
  83. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/b041b1fa4fe241b23445.woff2 +0 -0
  84. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/b6879d41b0852f01ed5b.woff2 +0 -0
  85. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
  86. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
  87. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/d75e3fd1eb12e9bd6655.ttf +0 -0
  88. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
  89. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/favicon.ico +0 -0
  90. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/index.css +0 -0
  91. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/index.css.map +0 -0
  92. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/index.html +0 -0
  93. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/index.js +0 -0
  94. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/index.js.map +0 -0
  95. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/login.html +0 -0
  96. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/server/data/manifest.json +0 -0
  97. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/settings.py +0 -0
  98. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/sphinx/static/experimaestro.css +0 -0
  99. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/taskglobals.py +0 -0
  100. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/__init__.py +0 -0
  101. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/conftest.py +0 -0
  102. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/connectors/bin/executable.py +0 -0
  103. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/connectors/test_local.py +0 -0
  104. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/connectors/utils.py +0 -0
  105. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/definitions_types.py +0 -0
  106. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/__init__.py +0 -0
  107. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/bin/sacct +0 -0
  108. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/bin/test.py +0 -0
  109. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/config_slurm/__init__.py +0 -0
  110. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/config_slurm/launchers.py +0 -0
  111. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/test_local.py +0 -0
  112. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/launchers/test_slurm.py +0 -0
  113. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/restart.py +0 -0
  114. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/restart_main.py +0 -0
  115. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/scripts/notifyandwait.py +0 -0
  116. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/scripts/waitforfile.py +0 -0
  117. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/task_tokens.py +0 -0
  118. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/tasks/__init__.py +0 -0
  119. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/tasks/all.py +0 -0
  120. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/tasks/foreign.py +0 -0
  121. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_checkers.py +0 -0
  122. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_dependencies.py +0 -0
  123. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_findlauncher.py +0 -0
  124. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_forward.py +0 -0
  125. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_identifier.py +0 -0
  126. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_instance.py +0 -0
  127. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_objects.py +0 -0
  128. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_outputs.py +0 -0
  129. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_param.py +0 -0
  130. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_progress.py +0 -0
  131. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_serializers.py +0 -0
  132. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_snippets.py +0 -0
  133. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_ssh.py +0 -0
  134. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_tags.py +0 -0
  135. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_tasks.py +0 -0
  136. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_tokens.py +0 -0
  137. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_types.py +0 -0
  138. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/test_validation.py +0 -0
  139. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/token_reschedule.py +0 -0
  140. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tests/utils.py +0 -0
  141. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tokens.py +0 -0
  142. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tools/__init__.py +0 -0
  143. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tools/diff.py +0 -0
  144. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tools/documentation.py +0 -0
  145. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/tools/jobs.py +0 -0
  146. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/typingutils.py +0 -0
  147. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/__init__.py +0 -0
  148. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/asyncio.py +0 -0
  149. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/jobs.py +0 -0
  150. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/jupyter.py +0 -0
  151. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/resources.py +0 -0
  152. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/utils/settings.py +0 -0
  153. {experimaestro-1.7.0rc1 → experimaestro-1.7.0rc3}/src/experimaestro/xpmutils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: experimaestro
3
- Version: 1.7.0rc1
3
+ Version: 1.7.0rc3
4
4
  Summary: "Experimaestro is a computer science experiment manager"
5
5
  License: GPL-3
6
6
  Keywords: experiment manager
@@ -20,7 +20,7 @@ include = [
20
20
  "src/experimaestro/mkdocs/style.css",
21
21
  { path="src/experimaestro/server/data/*", format=['sdist', 'wheel']}
22
22
  ]
23
- version = "1.7.0-rc1"
23
+ version = "1.7.0-rc3"
24
24
  repository = "https://github.com/experimaestro/experimaestro-python"
25
25
  documentation = "https://experimaestro-python.readthedocs.io/"
26
26
 
@@ -122,7 +122,7 @@ warn_unused_ignores = true
122
122
 
123
123
  [tool.commitizen]
124
124
  name = "cz_conventional_commits"
125
- version = "1.7.0rc0"
125
+ version = "1.7.0rc3"
126
126
  changelog_start_rev = "0.15.0"
127
127
  tag_format = "v$version"
128
128
  update_changelog_on_bump = true
@@ -276,12 +276,6 @@ class CommandLineJob(Job):
276
276
 
277
277
  scriptbuilder = self.launcher.scriptbuilder()
278
278
  self.path.mkdir(parents=True, exist_ok=True)
279
- donepath = self.donepath
280
-
281
- # Check again if done (now that we have locked)
282
- if not overwrite and donepath.is_file():
283
- logger.info("Job %s is already done", self)
284
- return JobState.DONE
285
279
 
286
280
  # Now we can write the script
287
281
  scriptbuilder.lockfiles.append(self.lockpath)
@@ -293,15 +287,17 @@ class CommandLineJob(Job):
293
287
  if self._process:
294
288
  return self._process
295
289
 
290
+ # Prepare the files to be run
296
291
  scriptPath = self.prepare()
297
292
 
293
+ # OK, now starts the process
298
294
  logger.info("Starting job %s", self.jobpath)
299
295
  processbuilder = self.launcher.processbuilder()
300
296
  processbuilder.environ = self.environ
301
297
  processbuilder.command.append(self.launcher.connector.resolve(scriptPath))
302
298
  processbuilder.stderr = Redirect.file(self.stderr)
303
299
  processbuilder.stdout = Redirect.file(self.stdout)
304
- self._process = processbuilder.start()
300
+ self._process = processbuilder.start(True)
305
301
 
306
302
  with self.pidpath.open("w") as fp:
307
303
  json.dump(self._process.tospec(), fp)
@@ -154,8 +154,11 @@ class ProcessBuilder:
154
154
  self.environ: Mapping[str, str] = {}
155
155
  self.command = []
156
156
 
157
- def start(self) -> Process:
158
- """Start the process"""
157
+ def start(self, task_mode: bool = False) -> Process:
158
+ """Start the process
159
+
160
+ :param task_mode: True if the process is a job script
161
+ """
159
162
  raise NotImplementedError("Method not implemented in %s" % self.__class__)
160
163
 
161
164
 
@@ -1,5 +1,4 @@
1
- """All classes related to localhost management
2
- """
1
+ """All classes related to localhost management"""
3
2
 
4
3
  import subprocess
5
4
  from typing import Optional
@@ -107,8 +106,11 @@ def getstream(redirect: Redirect, write: bool):
107
106
 
108
107
 
109
108
  class LocalProcessBuilder(ProcessBuilder):
110
- def start(self):
111
- """Start the process"""
109
+ def start(self, task_mode=False):
110
+ """Start the process
111
+
112
+ :param task_mode: just ignored
113
+ """
112
114
  stdin = getstream(self.stdin, False)
113
115
  stdout = getstream(self.stdout, True)
114
116
  stderr = getstream(self.stderr, True)
@@ -199,7 +201,9 @@ class LocalConnector(Connector):
199
201
  return LocalProcessBuilder()
200
202
 
201
203
  def resolve(self, path: Path, basepath: Path = None) -> str:
202
- assert isinstance(path, PosixPath) or isinstance(path, WindowsPath)
204
+ assert isinstance(path, PosixPath) or isinstance(
205
+ path, WindowsPath
206
+ ), f"Unrecognized path {type(path)}"
203
207
  if not basepath:
204
208
  return str(path.absolute())
205
209
  try:
@@ -200,7 +200,7 @@ class SshProcessBuilder(ProcessBuilder):
200
200
  super().__init__()
201
201
  self.connector = connector
202
202
 
203
- def start(self):
203
+ def start(self, task_mode: bool = False):
204
204
  """Start the process"""
205
205
 
206
206
  trans = str.maketrans({'"': r"\"", "$": r"\$"})
@@ -194,7 +194,11 @@ def experiments_cli( # noqa: C901
194
194
  xp_file = Path(xp_file)
195
195
  if not python_path:
196
196
  python_path.append(xp_file.parent)
197
- logging.info("Using python path: %s", ", ".join(str(s) for s in python_path))
197
+ logging.info(
198
+ "Using python path: %s", ", ".join(str(s) for s in python_path)
199
+ )
200
+ else:
201
+ xp_file = Path(xp_file)
198
202
 
199
203
  assert (
200
204
  module_name or xp_file
@@ -269,11 +273,11 @@ def experiments_cli( # noqa: C901
269
273
 
270
274
  # Define the workspace
271
275
  ws_env = find_workspace(workdir=workdir, workspace=workspace)
272
-
276
+
273
277
  workdir = ws_env.path
274
278
 
275
279
  logging.info("Using working directory %s", str(workdir.resolve()))
276
-
280
+
277
281
  # --- Runs the experiment
278
282
  with experiment(
279
283
  ws_env, configuration.id, host=host, port=port, run_mode=run_mode
@@ -8,7 +8,6 @@ import typing
8
8
  from omegaconf import DictConfig, OmegaConf, SCMode
9
9
  import pkg_resources
10
10
  from experimaestro.utils import logger
11
-
12
11
  from .base import ConnectorConfiguration, TokenConfiguration
13
12
  from .specs import HostRequirement
14
13
 
@@ -158,9 +157,14 @@ class LauncherRegistry:
158
157
  specs.append(spec)
159
158
 
160
159
  # Use launcher function
160
+ from experimaestro.launchers import Launcher
161
+
161
162
  if self.find_launcher_fn is not None:
162
163
  for spec in specs:
163
164
  if launcher := self.find_launcher_fn(spec, tags):
165
+ assert isinstance(
166
+ launcher, Launcher
167
+ ), "f{self.find_launcher_fn} did not return a Launcher but {type(launcher)}"
164
168
  return launcher
165
169
 
166
170
  return None
@@ -11,6 +11,7 @@ from typing import (
11
11
  )
12
12
  from experimaestro.connectors.local import LocalConnector
13
13
  import re
14
+ from shlex import quote as shquote
14
15
  from contextlib import contextmanager
15
16
  from dataclasses import dataclass
16
17
  from experimaestro.launcherfinder.registry import (
@@ -235,15 +236,15 @@ class SlurmProcessBuilder(ProcessBuilder):
235
236
  super().__init__()
236
237
  self.launcher = launcher
237
238
 
238
- def start(self) -> BatchSlurmProcess:
239
+ def start(self, task_mode: bool = False) -> BatchSlurmProcess:
239
240
  """Start the process"""
240
241
  builder = self.launcher.connector.processbuilder()
241
- builder.workingDirectory = self.workingDirectory
242
242
  builder.environ = self.launcher.launcherenv
243
243
  builder.detach = False
244
244
 
245
245
  if not self.detach:
246
246
  # Simplest case: we wait for the output
247
+ builder.workingDirectory = self.workingDirectory
247
248
  builder.command = [f"{self.launcher.binpath}/srun"]
248
249
  builder.command.extend(self.launcher.options.args())
249
250
  builder.command.extend(self.command)
@@ -255,11 +256,17 @@ class SlurmProcessBuilder(ProcessBuilder):
255
256
  return builder.start()
256
257
 
257
258
  builder.command = [f"{self.launcher.binpath}/sbatch", "--parsable"]
258
- builder.command.extend(self.launcher.options.args())
259
259
 
260
- addstream(builder.command, "-e", self.stderr)
261
- addstream(builder.command, "-o", self.stdout)
262
- addstream(builder.command, "-i", self.stdin)
260
+ if not task_mode:
261
+ # Use command line parameters when not running a task
262
+ builder.command.extend(self.launcher.options.args())
263
+
264
+ if self.workingDirectory:
265
+ workdir = self.launcher.connector.resolve(self.workingDirectory)
266
+ builder.command.append(f"--chdir={workdir}")
267
+ addstream(builder.command, "-e", self.stderr)
268
+ addstream(builder.command, "-o", self.stdout)
269
+ addstream(builder.command, "-i", self.stdin)
263
270
 
264
271
  builder.command.extend(self.command)
265
272
  logger.info(
@@ -427,12 +434,43 @@ class SlurmLauncher(Launcher):
427
434
 
428
435
  We assume *nix, but should be changed to PythonScriptBuilder when working
429
436
  """
430
- builder = PythonScriptBuilder()
431
- builder.processtype = "slurm"
432
- return builder
437
+ return SlurmScriptBuilder(self)
433
438
 
434
439
  def processbuilder(self) -> SlurmProcessBuilder:
435
440
  """Returns the process builder for this launcher
436
441
 
437
442
  By default, returns the associated connector builder"""
438
443
  return SlurmProcessBuilder(self)
444
+
445
+
446
+ class SlurmScriptBuilder(PythonScriptBuilder):
447
+ def __init__(self, launcher: SlurmLauncher, pythonpath=None):
448
+ super().__init__(pythonpath)
449
+ self.launcher = launcher
450
+ self.processtype = "slurm"
451
+
452
+ def write(self, job):
453
+ py_path = super().write(job)
454
+ main_path = py_path.parent
455
+
456
+ def relpath(path: Path):
457
+ return shquote(self.launcher.connector.resolve(path, main_path))
458
+
459
+ # Writes the sbatch shell script containing all the options
460
+ sh_path = job.jobpath / ("%s.sh" % job.name)
461
+ with sh_path.open("wt") as out:
462
+ out.write("""#!/bin/sh\n\n""")
463
+
464
+ workdir = self.launcher.connector.resolve(main_path)
465
+ out.write(f"#SBATCH --chdir={shquote(workdir)}\n")
466
+ out.write(f"""#SBATCH --error={relpath(job.stderr)}\n""")
467
+ out.write(f"""#SBATCH --output={relpath(job.stdout)}\n""")
468
+
469
+ for arg in self.launcher.options.args():
470
+ out.write(f"""#SBATCH {arg}\n""")
471
+
472
+ # We finish by the call to srun
473
+ out.write(f"""\nsrun ./{relpath(py_path)}\n\n""")
474
+
475
+ self.launcher.connector.setExecutable(sh_path, True)
476
+ return sh_path
@@ -740,6 +740,7 @@ class Scheduler:
740
740
  code = await process.aio_code()
741
741
  logger.debug("Got return code %s for %s", code, job)
742
742
 
743
+ # Check the file if there is no return code
743
744
  if code is None:
744
745
  # Case where we cannot retrieve the code right away
745
746
  if job.donepath.is_file():
@@ -916,6 +917,7 @@ class experiment:
916
917
 
917
918
  async def awaitcompletion():
918
919
  assert self.central is not None
920
+ logger.debug("Waiting to exit scheduler...")
919
921
  async with self.central.exitCondition:
920
922
  while True:
921
923
  if self.exitMode:
@@ -1011,6 +1013,7 @@ class experiment:
1011
1013
  return self
1012
1014
 
1013
1015
  def __exit__(self, exc_type, exc_value, traceback):
1016
+ logger.debug("Exiting scheduler context")
1014
1017
  # If no exception and normal run mode, remove old "jobs"
1015
1018
  if self.workspace.run_mode == RunMode.NORMAL:
1016
1019
  if exc_type is None and self.jobsbakpath.is_dir():
@@ -1051,6 +1054,7 @@ class experiment:
1051
1054
  # Put back old experiment as current one
1052
1055
  experiment.CURRENT = self.old_experiment
1053
1056
  if self.server:
1057
+ logger.info("Stopping web server")
1054
1058
  self.server.stop()
1055
1059
 
1056
1060
  async def update_task_output_count(self, delta: int):
@@ -135,7 +135,7 @@ class TaskOutputsWorker(threading.Thread):
135
135
  """This worker process dynamic output queue for one experiment"""
136
136
 
137
137
  def __init__(self, xp: experiment):
138
- super().__init__(name="task outputs worker")
138
+ super().__init__(name="task outputs worker", daemon=True)
139
139
  self.queue = queue.Queue()
140
140
  self.xp = xp
141
141
 
@@ -51,6 +51,8 @@ class PythonScriptBuilder:
51
51
  self.lockfiles: List[Path] = []
52
52
  self.notificationURL: Optional[str] = None
53
53
  self.command: Optional[AbstractCommand] = None
54
+
55
+ # This is used to serialize the full process identifier on disk
54
56
  self.processtype = "local"
55
57
 
56
58
  def write(self, job: CommandLineJob):
@@ -63,7 +65,7 @@ class PythonScriptBuilder:
63
65
  job {CommandLineJob} -- [description]
64
66
 
65
67
  Returns:
66
- [type] -- [description]
68
+ str -- The script path on disk
67
69
  """
68
70
  assert isinstance(
69
71
  job, CommandLineJob
@@ -10,19 +10,16 @@ from docutils import nodes
10
10
  from sphinx.application import Sphinx
11
11
  from sphinx import addnodes
12
12
  from sphinx.ext.autodoc import ClassDocumenter, Documenter, restify
13
- from sphinx.locale import _, __
13
+ from sphinx.locale import _
14
14
  from sphinx.util import inspect, logging
15
15
  from sphinx.domains.python import (
16
16
  PyClasslike,
17
17
  PyAttribute,
18
- PyObject,
19
- directives,
20
- desc_signature,
21
- _parse_annotation,
18
+ directives, # noqa: F401
22
19
  )
20
+ from sphinx.addnodes import desc_signature
23
21
  from sphinx.util.typing import OptionSpec
24
22
  from docutils.statemachine import StringList
25
- import logging
26
23
  import re
27
24
 
28
25
  from experimaestro import Config, Task
@@ -97,9 +94,6 @@ class ConfigDocumenter(ClassDocumenter):
97
94
  can_document = inspect.isclass(member) and issubclass(member, Config)
98
95
  return can_document
99
96
 
100
- def add_directive_header(self, sig: str) -> None:
101
- super().add_directive_header(sig)
102
-
103
97
  def get_object_members(self, want_all: bool): # -> Tuple[bool, ObjectMembers]:
104
98
  r = super().get_object_members(want_all)
105
99
  return r
@@ -157,7 +151,7 @@ class ConfigDocumenter(ClassDocumenter):
157
151
 
158
152
  # Our specific code
159
153
  if issubclass(self.object, Task):
160
- self.add_line(f" :task:", sourcename)
154
+ self.add_line(" :task:", sourcename)
161
155
 
162
156
  # add inheritance info, if wanted
163
157
  if not self.doc_as_attr and self.options.show_inheritance:
@@ -196,7 +190,6 @@ class ConfigDocumenter(ClassDocumenter):
196
190
  def add_content(
197
191
  self, more_content: Optional[StringList], no_docstring: bool = False
198
192
  ) -> None:
199
-
200
193
  xpminfo = getxpminfo(self.object)
201
194
  source_name = self.get_sourcename()
202
195
 
@@ -214,9 +207,9 @@ class ConfigDocumenter(ClassDocumenter):
214
207
  source_name,
215
208
  )
216
209
  if argument.generator:
217
- self.add_line(f" :generated:", source_name)
210
+ self.add_line(" :generated:", source_name)
218
211
  elif argument.constant:
219
- self.add_line(f" :constant:", source_name)
212
+ self.add_line(" :constant:", source_name)
220
213
 
221
214
  # self.add_line("", source_name)
222
215
  if argument.help:
@@ -2,8 +2,11 @@
2
2
 
3
3
  # slurm test suite
4
4
 
5
+ pwd 1>&2
6
+ CURDIR="$(realpath "$(dirname "$0")"/..)"
7
+
5
8
  # Where we store the jobs
6
- XPM_SLURM_DIR="$(realpath "$(dirname "$0")"/..)/slurm"
9
+ XPM_SLURM_DIR="${CURDIR}/slurm"
7
10
  if ! test -d "$XPM_SLURM_DIR"; then
8
11
  echo "Directory $XPM_SLURM_DIR does not exist" 1>&2
9
12
  exit 1
@@ -51,8 +54,19 @@ while true; do
51
54
  esac
52
55
  done
53
56
 
54
- echo "Starting $@ ${args[@]} > $stdout" >&2
57
+ chdir=$(pwd)
58
+ while IFS= read -r line; do
59
+ case "$line" in
60
+ "#SBATCH --output="*)stdout=${line#*#SBATCH --output=};;
61
+ "#SBATCH --error="*) stderr=${line#*#SBATCH --error=};;
62
+ "#SBATCH --chdir="*) chdir=${line#*#SBATCH --chdir=};;
63
+ esac
64
+ done < "$1"
65
+
66
+ echo "Starting $@ ${args[@]} > $stdout 2> $stderr" >&2
55
67
  (
68
+ if test "$chdir"; then cd "$chdir"; fi
69
+ export PATH="${CURDIR}/bin:$PATH"
56
70
  eval "$@" "${args[@]}"
57
71
  echo $? > "$XPM_SLURM_DIR/jobs/$$.status"
58
72
  ) > $stdout 2> $stderr &
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ # Just run the command
4
+
5
+ eval "$@"
@@ -80,10 +80,14 @@ def takeback(launcher, datapath, txp1, txp2):
80
80
  waiting = datapath / "waiting"
81
81
 
82
82
  with txp1:
83
- WaitUntilTouched(touching=touching, waiting=waiting).submit(launcher=launcher)
83
+ task: WaitUntilTouched = WaitUntilTouched(
84
+ touching=touching, waiting=waiting
85
+ ).submit(launcher=launcher)
84
86
 
85
87
  logger.debug("Waiting for task to create 'touching' file")
86
88
  while not touching.is_file():
89
+ if task.__xpm__.job.state.finished():
90
+ raise Exception("Job has finished... too early")
87
91
  time.sleep(0.01)
88
92
 
89
93
  with txp2: