experimaestro 1.8.0rc2__tar.gz → 1.8.0rc4__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 (156) hide show
  1. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/PKG-INFO +1 -1
  2. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/pyproject.toml +3 -3
  3. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/__init__.py +9 -1
  4. experimaestro-1.8.0rc4/src/experimaestro/core/callbacks.py +52 -0
  5. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/objects.py +16 -0
  6. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/serialization.py +52 -2
  7. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/base.py +2 -0
  8. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_experiment.py +23 -0
  9. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/LICENSE +0 -0
  10. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/README.md +0 -0
  11. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/__main__.py +0 -0
  12. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/annotations.py +0 -0
  13. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/checkers.py +0 -0
  14. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/cli/__init__.py +0 -0
  15. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/cli/filter.py +0 -0
  16. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/cli/jobs.py +0 -0
  17. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/click.py +0 -0
  18. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/commandline.py +0 -0
  19. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/compat.py +0 -0
  20. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/connectors/__init__.py +0 -0
  21. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/connectors/local.py +0 -0
  22. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/connectors/ssh.py +0 -0
  23. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/__init__.py +0 -0
  24. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/arguments.py +0 -0
  25. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/context.py +0 -0
  26. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/objects.pyi +0 -0
  27. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/serializers.py +0 -0
  28. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/types.py +0 -0
  29. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/core/utils.py +0 -0
  30. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/exceptions.py +0 -0
  31. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/experiments/__init__.py +0 -0
  32. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/experiments/cli.py +0 -0
  33. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/experiments/configuration.py +0 -0
  34. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/generators.py +0 -0
  35. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/huggingface.py +0 -0
  36. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/ipc.py +0 -0
  37. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launcherfinder/__init__.py +0 -0
  38. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launcherfinder/base.py +0 -0
  39. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launcherfinder/parser.py +0 -0
  40. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launcherfinder/registry.py +0 -0
  41. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launcherfinder/specs.py +0 -0
  42. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launchers/__init__.py +0 -0
  43. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launchers/direct.py +0 -0
  44. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launchers/oar.py +0 -0
  45. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launchers/slurm/__init__.py +0 -0
  46. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/launchers/slurm/base.py +0 -0
  47. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/locking.py +0 -0
  48. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mkdocs/__init__.py +0 -0
  49. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mkdocs/annotations.py +0 -0
  50. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mkdocs/base.py +0 -0
  51. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mkdocs/metaloader.py +0 -0
  52. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mkdocs/style.css +0 -0
  53. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/mypy.py +0 -0
  54. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/notifications.py +0 -0
  55. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/py.typed +0 -0
  56. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/rpyc.py +0 -0
  57. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/run.py +0 -0
  58. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/__init__.py +0 -0
  59. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/dependencies.py +0 -0
  60. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/dynamic_outputs.py +0 -0
  61. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/services.py +0 -0
  62. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/state.py +0 -0
  63. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scheduler/workspace.py +0 -0
  64. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/scriptbuilder.py +0 -0
  65. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/__init__.py +0 -0
  66. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/016b4a6cdced82ab3aa1.ttf +0 -0
  67. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
  68. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
  69. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
  70. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
  71. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
  72. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
  73. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
  74. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
  75. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
  76. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/50701fbb8177c2dde530.ttf +0 -0
  77. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
  78. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
  79. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/878f31251d960bd6266f.woff2 +0 -0
  80. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
  81. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
  82. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/b041b1fa4fe241b23445.woff2 +0 -0
  83. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/b6879d41b0852f01ed5b.woff2 +0 -0
  84. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
  85. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
  86. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/d75e3fd1eb12e9bd6655.ttf +0 -0
  87. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
  88. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/favicon.ico +0 -0
  89. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/index.css +0 -0
  90. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/index.css.map +0 -0
  91. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/index.html +0 -0
  92. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/index.js +0 -0
  93. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/index.js.map +0 -0
  94. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/login.html +0 -0
  95. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/server/data/manifest.json +0 -0
  96. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/settings.py +0 -0
  97. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/sphinx/__init__.py +0 -0
  98. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/sphinx/static/experimaestro.css +0 -0
  99. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/taskglobals.py +0 -0
  100. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/__init__.py +0 -0
  101. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/conftest.py +0 -0
  102. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/connectors/bin/executable.py +0 -0
  103. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/connectors/test_local.py +0 -0
  104. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/connectors/utils.py +0 -0
  105. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/definitions_types.py +0 -0
  106. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/__init__.py +0 -0
  107. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/bin/sacct +0 -0
  108. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/bin/sbatch +0 -0
  109. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/bin/srun +0 -0
  110. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/bin/test.py +0 -0
  111. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/common.py +0 -0
  112. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/config_slurm/__init__.py +0 -0
  113. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/config_slurm/launchers.py +0 -0
  114. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/test_local.py +0 -0
  115. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/launchers/test_slurm.py +0 -0
  116. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/restart.py +0 -0
  117. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/restart_main.py +0 -0
  118. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/scripts/notifyandwait.py +0 -0
  119. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/scripts/waitforfile.py +0 -0
  120. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/task_tokens.py +0 -0
  121. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/tasks/__init__.py +0 -0
  122. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/tasks/all.py +0 -0
  123. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/tasks/foreign.py +0 -0
  124. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_checkers.py +0 -0
  125. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_dependencies.py +0 -0
  126. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_findlauncher.py +0 -0
  127. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_forward.py +0 -0
  128. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_identifier.py +0 -0
  129. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_instance.py +0 -0
  130. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_objects.py +0 -0
  131. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_outputs.py +0 -0
  132. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_param.py +0 -0
  133. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_progress.py +0 -0
  134. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_serializers.py +0 -0
  135. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_snippets.py +0 -0
  136. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_ssh.py +0 -0
  137. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_tags.py +0 -0
  138. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_tasks.py +0 -0
  139. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_tokens.py +0 -0
  140. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_types.py +0 -0
  141. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/test_validation.py +0 -0
  142. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/token_reschedule.py +0 -0
  143. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tests/utils.py +0 -0
  144. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tokens.py +0 -0
  145. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tools/__init__.py +0 -0
  146. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tools/diff.py +0 -0
  147. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tools/documentation.py +0 -0
  148. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/tools/jobs.py +0 -0
  149. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/typingutils.py +0 -0
  150. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/__init__.py +0 -0
  151. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/asyncio.py +0 -0
  152. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/jobs.py +0 -0
  153. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/jupyter.py +0 -0
  154. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/resources.py +0 -0
  155. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/utils/settings.py +0 -0
  156. {experimaestro-1.8.0rc2 → experimaestro-1.8.0rc4}/src/experimaestro/xpmutils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: experimaestro
3
- Version: 1.8.0rc2
3
+ Version: 1.8.0rc4
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.8.0-rc2"
23
+ version = "1.8.0-rc4"
24
24
  repository = "https://github.com/experimaestro/experimaestro-python"
25
25
  documentation = "https://experimaestro-python.readthedocs.io/"
26
26
 
@@ -117,12 +117,12 @@ max-line-length = "88"
117
117
  extend-ignore = "E203"
118
118
 
119
119
  [tool.mypy]
120
- python_version = "3.9"
120
+ python_version = "3.10"
121
121
  warn_unused_ignores = true
122
122
 
123
123
  [tool.commitizen]
124
124
  name = "cz_conventional_commits"
125
- version = "1.8.0rc2"
125
+ version = "1.8.0rc4"
126
126
  changelog_start_rev = "v1.0.0"
127
127
  tag_format = "v$major.$minor.$patch$prerelease"
128
128
  # update_changelog_on_bump = true
@@ -27,7 +27,15 @@ from .annotations import (
27
27
  # Method
28
28
  config_only,
29
29
  )
30
- from .core.serialization import load, save, state_dict, from_state_dict, from_task_dir
30
+ from .core.serialization import (
31
+ load,
32
+ save,
33
+ state_dict,
34
+ from_state_dict,
35
+ from_task_dir,
36
+ serialize,
37
+ deserialize,
38
+ )
31
39
  from .core.arguments import (
32
40
  # Types
33
41
  Param,
@@ -0,0 +1,52 @@
1
+ from collections import defaultdict
2
+ import threading
3
+ from typing import Callable, ClassVar, Optional
4
+ from experimaestro.core.objects import ConfigInformation
5
+ from experimaestro.scheduler import Listener, Job, JobState, experiment
6
+
7
+
8
+ class TaskEventListener(Listener):
9
+ INSTANCE: ClassVar[Optional["TaskEventListener"]] = None
10
+ """The general instance"""
11
+
12
+ def __init__(self):
13
+ self.lock = threading.Lock()
14
+ self.experiments: set[int] = set()
15
+
16
+ self._on_completed: defaultdict[int, Callable] = defaultdict(list)
17
+
18
+ @staticmethod
19
+ def connect(xp: experiment):
20
+ _self = TaskEventListener.instance()
21
+ with _self.lock:
22
+ if id(xp) not in _self.experiments:
23
+ _self.experiments.add(id(xp))
24
+ xp.scheduler.addlistener(_self)
25
+
26
+ @staticmethod
27
+ def instance():
28
+ if TaskEventListener.INSTANCE is None:
29
+ TaskEventListener.INSTANCE = TaskEventListener()
30
+
31
+ return TaskEventListener.INSTANCE
32
+
33
+ def job_state(self, job: Job):
34
+ if job.state == JobState.DONE:
35
+ with self.lock:
36
+ for callback in self._on_completed.get(id(job.config.__xpm__), []):
37
+ callback()
38
+
39
+ @staticmethod
40
+ def on_completed(
41
+ config_information: ConfigInformation, callback: Callable[[], None]
42
+ ):
43
+ instance = TaskEventListener.instance()
44
+
45
+ with instance.lock:
46
+ instance._on_completed[id(config_information)].append(callback)
47
+
48
+ if (
49
+ config_information.job is not None
50
+ and config_information.job == JobState.DONE
51
+ ):
52
+ callback()
@@ -47,6 +47,7 @@ from experimaestro.core.types import DeprecatedAttribute, ObjectType
47
47
  from .context import SerializationContext, SerializedPath, SerializedPathLoader
48
48
 
49
49
  if TYPE_CHECKING:
50
+ from .callbacks import TaskEventListener
50
51
  from experimaestro.scheduler.base import Job
51
52
  from experimaestro.scheduler.workspace import RunMode
52
53
  from experimaestro.launchers import Launcher
@@ -607,6 +608,7 @@ class ConfigInformation:
607
608
 
608
609
  # State information
609
610
  self.job = None
611
+ self._job_listener: "TaskEventListener" | None = None
610
612
 
611
613
  #: True when this configuration was loaded from disk
612
614
  self.loaded = False
@@ -947,6 +949,15 @@ class ConfigInformation:
947
949
  if self.job:
948
950
  self.job.watch_output(watched)
949
951
 
952
+ def on_completed(self, callback: Callable[[], None]):
953
+ """Call a method when the task is completed successfully
954
+
955
+ :param callback: _description_
956
+ """
957
+ from .callbacks import TaskEventListener
958
+
959
+ TaskEventListener.on_completed(self, callback)
960
+
950
961
  def submit(
951
962
  self,
952
963
  workspace: "Workspace",
@@ -957,6 +968,7 @@ class ConfigInformation:
957
968
  ):
958
969
  from experimaestro.scheduler import experiment, JobContext
959
970
  from experimaestro.scheduler.workspace import RunMode
971
+ from .callbacks import TaskEventListener
960
972
 
961
973
  # --- Prepare the object
962
974
 
@@ -1009,6 +1021,7 @@ class ConfigInformation:
1009
1021
  workspace.run_mode if run_mode is None else run_mode
1010
1022
  ) or RunMode.NORMAL
1011
1023
  if run_mode == RunMode.NORMAL:
1024
+ TaskEventListener.connect(experiment.CURRENT)
1012
1025
  other = experiment.CURRENT.submit(self.job)
1013
1026
  if other:
1014
1027
  # Just returns the other task
@@ -2015,6 +2028,9 @@ class Task(LightweightTask):
2015
2028
  """
2016
2029
  self.__xpm__.watch_output(method, callback)
2017
2030
 
2031
+ def on_completed(self, callback: Callable[[], None]):
2032
+ self.__xpm__.on_completed(callback)
2033
+
2018
2034
 
2019
2035
  # --- Utility functions
2020
2036
 
@@ -36,7 +36,7 @@ def state_dict(context: SerializationContext, obj: Any):
36
36
  :param context: The serialization context
37
37
  :param obj: the object to serialize
38
38
  """
39
- objects = []
39
+ objects: list[Any] = []
40
40
  data = json_object(context, obj, objects)
41
41
  return {"objects": objects, "data": data}
42
42
 
@@ -50,11 +50,17 @@ def save_definition(obj: Any, context: SerializationContext, path: Path):
50
50
  def save(obj: Any, save_directory: Optional[Path]):
51
51
  """Saves an object into a disk file
52
52
 
53
+ The serialization process also stores in the given folder the different
54
+ files or folders that are registered as Path parameters (or
55
+ meta-parameters).
56
+
53
57
  :param save_directory: The directory in which the object and its data will
54
58
  be saved (by default, the object is saved in "definition.json")
55
59
  """
56
60
  context = SerializationContext(save_directory=save_directory)
57
- save_definition(obj, context, save_directory / "definition.json")
61
+ save_definition(
62
+ obj, context, save_directory / "definition.json" if save_directory else None
63
+ )
58
64
 
59
65
 
60
66
  def get_data_loader(path: Union[str, Path, SerializedPathLoader]):
@@ -129,3 +135,47 @@ def from_task_dir(
129
135
  content["data"] = {"type": "python", "value": content["objects"][-1]["id"]}
130
136
 
131
137
  return from_state_dict(content, as_instance=as_instance)
138
+
139
+
140
+ def serialize(
141
+ obj: Any, save_directory: Path, *, init_tasks: list["LightweightTask"] = []
142
+ ):
143
+ """Saves an object into a disk file, including initialization tasks
144
+
145
+ The serialization process also stores in the given folder the different
146
+ files or folders that are registered as Path parameters (or
147
+ meta-parameters).
148
+
149
+ :param save_directory: The directory in which the object and its data will
150
+ be saved (by default, the object is saved in "definition.json")
151
+ :param init_tasks: The optional
152
+ """
153
+ context = SerializationContext(save_directory=save_directory)
154
+ save_definition((obj, init_tasks), context, save_directory / "definition.json")
155
+
156
+
157
+ def deserialize(
158
+ path: Union[str, Path, SerializedPathLoader],
159
+ as_instance: bool = False,
160
+ ) -> tuple[Any, List["LightweightTask"]] | Any:
161
+ """Load data from disk, and initialize the object
162
+
163
+ :param path: A directory or a function that transforms relative file path
164
+ into absolute ones
165
+ :param as_instance: returns instances instead of configuration objects
166
+ :returns: either the object (as_instance is true), or a tuple
167
+ """
168
+ data_loader = get_data_loader(path)
169
+
170
+ with data_loader("definition.json").open("rt") as fh:
171
+ content = json.load(fh)
172
+
173
+ object, init_tasks = from_state_dict(content, as_instance=as_instance)
174
+
175
+ if as_instance:
176
+ for init_task in init_tasks:
177
+ init_task.execute()
178
+
179
+ return object
180
+
181
+ return object, init_tasks
@@ -819,6 +819,7 @@ class experiment:
819
819
  """
820
820
 
821
821
  from experimaestro.server import Server
822
+ from experimaestro.scheduler import Listener
822
823
 
823
824
  settings = get_settings()
824
825
  if not isinstance(env, WorkspaceSettings):
@@ -835,6 +836,7 @@ class experiment:
835
836
  self.xplock = None
836
837
  self.old_experiment = None
837
838
  self.services: Dict[str, Service] = {}
839
+ self._job_listener: Optional[Listener] = None
838
840
 
839
841
  # Get configuration settings
840
842
 
@@ -48,3 +48,26 @@ def test_experiment_history():
48
48
  (task_b_info,) = xp.get_jobs(TaskB)
49
49
  assert task_b_info.tags == {"x": 1}
50
50
  assert task_b_info.depends_on == [task_a_info]
51
+
52
+
53
+ class FlagHandler:
54
+ def __init__(self):
55
+ self.flag = False
56
+
57
+ def set(self):
58
+ self.flag = True
59
+
60
+ def is_set(self):
61
+ return self.flag
62
+
63
+
64
+ def test_experiment_events():
65
+ """Test handlers"""
66
+
67
+ flag = FlagHandler()
68
+ with TemporaryExperiment("experiment"):
69
+ task_a = TaskA()
70
+ task_a.submit()
71
+ task_a.on_completed(flag.set)
72
+
73
+ assert flag.is_set()