experimaestro 1.10.1__tar.gz → 1.12.0__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 (157) hide show
  1. {experimaestro-1.10.1 → experimaestro-1.12.0}/PKG-INFO +5 -4
  2. {experimaestro-1.10.1 → experimaestro-1.12.0}/pyproject.toml +4 -4
  3. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launcherfinder/specs.py +8 -1
  4. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/run.py +2 -0
  5. experimaestro-1.12.0/src/experimaestro/utils/multiprocessing.py +44 -0
  6. {experimaestro-1.10.1 → experimaestro-1.12.0}/LICENSE +0 -0
  7. {experimaestro-1.10.1 → experimaestro-1.12.0}/README.md +0 -0
  8. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/__init__.py +0 -0
  9. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/__main__.py +0 -0
  10. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/annotations.py +0 -0
  11. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/checkers.py +0 -0
  12. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/cli/__init__.py +0 -0
  13. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/cli/filter.py +0 -0
  14. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/cli/jobs.py +0 -0
  15. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/click.py +0 -0
  16. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/commandline.py +0 -0
  17. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/compat.py +0 -0
  18. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/connectors/__init__.py +0 -0
  19. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/connectors/local.py +0 -0
  20. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/connectors/ssh.py +0 -0
  21. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/__init__.py +0 -0
  22. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/arguments.py +0 -0
  23. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/callbacks.py +0 -0
  24. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/context.py +0 -0
  25. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/identifier.py +0 -0
  26. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/objects/__init__.py +0 -0
  27. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/objects/config.py +0 -0
  28. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/objects/config_utils.py +0 -0
  29. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/objects/config_walk.py +0 -0
  30. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/objects.pyi +0 -0
  31. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/serialization.py +0 -0
  32. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/serializers.py +0 -0
  33. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/types.py +0 -0
  34. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/core/utils.py +0 -0
  35. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/exceptions.py +0 -0
  36. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/experiments/__init__.py +0 -0
  37. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/experiments/cli.py +0 -0
  38. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/experiments/configuration.py +0 -0
  39. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/generators.py +0 -0
  40. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/huggingface.py +0 -0
  41. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/ipc.py +0 -0
  42. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launcherfinder/__init__.py +0 -0
  43. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launcherfinder/base.py +0 -0
  44. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launcherfinder/parser.py +0 -0
  45. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launcherfinder/registry.py +0 -0
  46. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launchers/__init__.py +0 -0
  47. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launchers/direct.py +0 -0
  48. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launchers/oar.py +0 -0
  49. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launchers/slurm/__init__.py +0 -0
  50. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/launchers/slurm/base.py +0 -0
  51. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/locking.py +0 -0
  52. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mkdocs/__init__.py +0 -0
  53. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mkdocs/annotations.py +0 -0
  54. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mkdocs/base.py +0 -0
  55. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mkdocs/metaloader.py +0 -0
  56. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mkdocs/style.css +0 -0
  57. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/mypy.py +0 -0
  58. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/notifications.py +0 -0
  59. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/py.typed +0 -0
  60. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/rpyc.py +0 -0
  61. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/__init__.py +0 -0
  62. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/base.py +0 -0
  63. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/dependencies.py +0 -0
  64. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/dynamic_outputs.py +0 -0
  65. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/services.py +0 -0
  66. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/state.py +0 -0
  67. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scheduler/workspace.py +0 -0
  68. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/scriptbuilder.py +0 -0
  69. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/__init__.py +0 -0
  70. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/0c35d18bf06992036b69.woff2 +0 -0
  71. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/1815e00441357e01619e.ttf +0 -0
  72. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/219aa9140e099e6c72ed.woff2 +0 -0
  73. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/2463b90d9a316e4e5294.woff2 +0 -0
  74. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/2582b0e4bcf85eceead0.ttf +0 -0
  75. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/3a4004a46a653d4b2166.woff +0 -0
  76. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/3baa5b8f3469222b822d.woff +0 -0
  77. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/4d73cb90e394b34b7670.woff +0 -0
  78. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/4ef4218c522f1eb6b5b1.woff2 +0 -0
  79. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/5d681e2edae8c60630db.woff +0 -0
  80. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/6f420cf17cc0d7676fad.woff2 +0 -0
  81. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/89999bdf5d835c012025.woff2 +0 -0
  82. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/914997e1bdfc990d0897.ttf +0 -0
  83. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/c210719e60948b211a12.woff2 +0 -0
  84. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/c380809fd3677d7d6903.woff2 +0 -0
  85. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/f882956fd323fd322f31.woff +0 -0
  86. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/favicon.ico +0 -0
  87. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/index.css +0 -0
  88. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/index.css.map +0 -0
  89. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/index.html +0 -0
  90. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/index.js +0 -0
  91. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/index.js.map +0 -0
  92. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/login.html +0 -0
  93. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/server/data/manifest.json +0 -0
  94. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/settings.py +0 -0
  95. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/sphinx/__init__.py +0 -0
  96. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/sphinx/static/experimaestro.css +0 -0
  97. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/taskglobals.py +0 -0
  98. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/__init__.py +0 -0
  99. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/conftest.py +0 -0
  100. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/connectors/bin/executable.py +0 -0
  101. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/connectors/test_local.py +0 -0
  102. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/connectors/utils.py +0 -0
  103. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/core/__init__.py +0 -0
  104. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/core/test_generics.py +0 -0
  105. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/definitions_types.py +0 -0
  106. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/__init__.py +0 -0
  107. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/bin/sacct +0 -0
  108. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/bin/sbatch +0 -0
  109. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/bin/srun +0 -0
  110. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/bin/test.py +0 -0
  111. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/common.py +0 -0
  112. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/config_slurm/__init__.py +0 -0
  113. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/config_slurm/launchers.py +0 -0
  114. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/test_local.py +0 -0
  115. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/launchers/test_slurm.py +0 -0
  116. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/restart.py +0 -0
  117. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/restart_main.py +0 -0
  118. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/scripts/notifyandwait.py +0 -0
  119. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/scripts/waitforfile.py +0 -0
  120. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/task_tokens.py +0 -0
  121. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/tasks/__init__.py +0 -0
  122. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/tasks/all.py +0 -0
  123. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/tasks/foreign.py +0 -0
  124. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_checkers.py +0 -0
  125. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_dependencies.py +0 -0
  126. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_experiment.py +0 -0
  127. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_findlauncher.py +0 -0
  128. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_forward.py +0 -0
  129. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_identifier.py +0 -0
  130. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_instance.py +0 -0
  131. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_objects.py +0 -0
  132. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_outputs.py +0 -0
  133. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_param.py +0 -0
  134. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_progress.py +0 -0
  135. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_serializers.py +0 -0
  136. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_snippets.py +0 -0
  137. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_ssh.py +0 -0
  138. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_tags.py +0 -0
  139. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_tasks.py +0 -0
  140. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_tokens.py +0 -0
  141. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_types.py +0 -0
  142. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/test_validation.py +0 -0
  143. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/token_reschedule.py +0 -0
  144. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tests/utils.py +0 -0
  145. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tokens.py +0 -0
  146. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tools/__init__.py +0 -0
  147. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tools/diff.py +0 -0
  148. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tools/documentation.py +0 -0
  149. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/tools/jobs.py +0 -0
  150. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/typingutils.py +0 -0
  151. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/__init__.py +0 -0
  152. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/asyncio.py +0 -0
  153. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/jobs.py +0 -0
  154. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/jupyter.py +0 -0
  155. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/resources.py +0 -0
  156. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/utils/settings.py +0 -0
  157. {experimaestro-1.10.1 → experimaestro-1.12.0}/src/experimaestro/xpmutils.py +0 -0
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: experimaestro
3
- Version: 1.10.1
3
+ Version: 1.12.0
4
4
  Summary: "Experimaestro is a computer science experiment manager"
5
5
  License: GPL-3
6
+ License-File: LICENSE
6
7
  Keywords: experiment manager
7
8
  Author: Benjamin Piwowarski
8
9
  Author-email: benjamin@piwowarski.fr
@@ -20,8 +21,8 @@ Requires-Dist: click (>=8)
20
21
  Requires-Dist: decorator (>=5,<6)
21
22
  Requires-Dist: docstring-parser (>=0.15,<1)
22
23
  Requires-Dist: fasteners (>=0.19,<1)
23
- Requires-Dist: flask (>=2.3,<3)
24
- Requires-Dist: flask-socketio (>=5.3,<6)
24
+ Requires-Dist: flask (>=2.3)
25
+ Requires-Dist: flask-socketio (>=5.3)
25
26
  Requires-Dist: gevent (>=25)
26
27
  Requires-Dist: gevent-websocket (>=0.10)
27
28
  Requires-Dist: huggingface-hub (>0.17)
@@ -27,8 +27,8 @@ dependencies = [
27
27
  "decorator >=5,<6",
28
28
  "docstring-parser >=0.15,<1",
29
29
  "fasteners >=0.19,<1",
30
- "flask >=2.3,<3",
31
- "flask-socketio >=5.3,<6",
30
+ "flask >=2.3",
31
+ "flask-socketio >=5.3",
32
32
  "gevent >=25",
33
33
  "gevent-websocket >=0.10",
34
34
  "humanfriendly >=10",
@@ -48,7 +48,7 @@ dependencies = [
48
48
  "typing-extensions >=4.2; python_version < \"3.12\"",
49
49
  "watchdog >=2"
50
50
  ]
51
- version = "1.10.1"
51
+ version = "1.12.0"
52
52
 
53
53
  [tool.poetry-dynamic-versioning]
54
54
  enable = false
@@ -140,7 +140,7 @@ warn_unused_ignores = true
140
140
 
141
141
  [tool.commitizen]
142
142
  name = "cz_conventional_commits"
143
- version = "1.11.0"
143
+ version = "1.12.0"
144
144
  changelog_start_rev = "v1.0.0"
145
145
  tag_format = "v$major.$minor.$patch$prerelease"
146
146
  # update_changelog_on_bump = true
@@ -29,7 +29,7 @@ class CudaSpecification:
29
29
  def __repr__(self):
30
30
  return (
31
31
  f"CUDA({self.model} "
32
- f"max={format_size(self.memory)}/min={format_size(self.min_memory)})"
32
+ f"max={format_size(self.memory, binary=True)}/min={format_size(self.min_memory, binary=True)})"
33
33
  )
34
34
 
35
35
 
@@ -47,6 +47,13 @@ class CPUSpecification:
47
47
  cpu_per_gpu: int = 0
48
48
  """Number of CPU per GPU (0 if not defined)"""
49
49
 
50
+ def __repr__(self):
51
+ return (
52
+ f"CPU("
53
+ f"mem={format_size(self.memory, binary=True)}, cores={self.cores}"
54
+ ")"
55
+ )
56
+
50
57
  def match(self, other: "CPUSpecification"):
51
58
  return (self.memory >= other.memory) and (self.cores >= other.cores)
52
59
 
@@ -8,6 +8,7 @@ import json
8
8
  from typing import List
9
9
  import fasteners
10
10
  from experimaestro.notifications import progress, report_eoj
11
+ from experimaestro.utils.multiprocessing import delayed_shutdown
11
12
  from .core.types import ObjectType
12
13
  from experimaestro.utils import logger
13
14
  from experimaestro.core.objects import ConfigInformation
@@ -96,6 +97,7 @@ class TaskRunner:
96
97
  self.failedpath.write_text(str(code))
97
98
  self.cleanup()
98
99
  logger.info("Exiting")
100
+ delayed_shutdown(60, exit_code=code)
99
101
  sys.exit(1)
100
102
 
101
103
  def run(self):
@@ -0,0 +1,44 @@
1
+ import logging
2
+ import multiprocessing as mp
3
+ import time
4
+ import os
5
+ import signal
6
+ import threading
7
+
8
+
9
+ def delayed_shutdown(delay=60, *, exit_code=1, grace_period=5):
10
+ """After *delay*'s try a graceful stop, then SIGKILL anything left.
11
+
12
+ :param delay: Delay in seconds before killing
13
+ :param grace_period: Delay in seconds before force-killing a child process
14
+ :param exit_code: The exit code to use
15
+ """
16
+
17
+ def _killer():
18
+ time.sleep(delay)
19
+
20
+ logging.info("Stall dectected – killing all subprocesses")
21
+
22
+ # 1️⃣ Try graceful termination
23
+ for p in mp.active_children():
24
+ # sends SIGTERM / TerminateProcess
25
+ p.terminate()
26
+
27
+ alive = mp.active_children()
28
+ deadline = time.time() + grace_period
29
+ while alive and time.time() < deadline:
30
+ alive = [p for p in alive if p.is_alive()]
31
+ time.sleep(0.1)
32
+
33
+ # 2️⃣ Anything still alive? Nuke it.
34
+ for p in alive:
35
+ try:
36
+ os.kill(p.pid, signal.SIGKILL)
37
+ except OSError:
38
+ pass
39
+
40
+ # 3️⃣ Finally kill the parent
41
+ os.kill(os.getpid(), signal.SIGKILL)
42
+
43
+ # Start the thread (non blocking)
44
+ threading.Thread(target=_killer, daemon=True).start()
File without changes
File without changes