simstack 2.0.1__py3-none-any.whl

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.
Files changed (354) hide show
  1. simstack/__init__.py +0 -0
  2. simstack/_version.py +24 -0
  3. simstack/core/__init__.py +0 -0
  4. simstack/core/artifacts.py +406 -0
  5. simstack/core/asnyc_helper.py +14 -0
  6. simstack/core/config_file.py +60 -0
  7. simstack/core/context.py +283 -0
  8. simstack/core/definitions.py +22 -0
  9. simstack/core/engine.py +115 -0
  10. simstack/core/find_simstack_modules.py +41 -0
  11. simstack/core/hash.py +179 -0
  12. simstack/core/node.py +1137 -0
  13. simstack/core/node_claim.py +31 -0
  14. simstack/core/node_runner.py +362 -0
  15. simstack/core/process_results.py +102 -0
  16. simstack/core/recompute_artifacts.py +117 -0
  17. simstack/core/reset_db.py +12 -0
  18. simstack/core/resource_assignment.py +222 -0
  19. simstack/core/resources.py +90 -0
  20. simstack/core/route_table.py +24 -0
  21. simstack/core/run_docker.py +109 -0
  22. simstack/core/run_node.py +71 -0
  23. simstack/core/runner.py +169 -0
  24. simstack/core/services/__init__.py +11 -0
  25. simstack/core/services/base_service.py +191 -0
  26. simstack/core/services/file_transfer_service.py +117 -0
  27. simstack/core/services/git_restart_service.py +12 -0
  28. simstack/core/services/git_uv_update_service.py +105 -0
  29. simstack/core/services/node_execution_service.py +182 -0
  30. simstack/core/services/resource_branch_monitor_service.py +71 -0
  31. simstack/core/services/runner_cleanup_service.py +149 -0
  32. simstack/core/services/runner_manager.py +163 -0
  33. simstack/core/services/runner_status_service.py +10 -0
  34. simstack/core/services/slurm_status_service.py +67 -0
  35. simstack/core/services/stop_check_service.py +27 -0
  36. simstack/core/services/timeout_restart_service.py +26 -0
  37. simstack/core/simstack_result.py +39 -0
  38. simstack/core/submit_node.py +217 -0
  39. simstack/core/task_id.py +22 -0
  40. simstack/methods/__init__.py +0 -0
  41. simstack/methods/archive_files.py +292 -0
  42. simstack/methods/fire_and_forget_runner.py +113 -0
  43. simstack/methods/generate_test.py +125 -0
  44. simstack/methods/get_file.py +26 -0
  45. simstack/methods/mass_runner.py +154 -0
  46. simstack/methods/multiple_executor.py +307 -0
  47. simstack/methods/switch_git.py +16 -0
  48. simstack/methods/upload_helpers.py +81 -0
  49. simstack/models/__init__.py +74 -0
  50. simstack/models/array_list.py +21 -0
  51. simstack/models/array_storage.py +83 -0
  52. simstack/models/artifact_models.py +127 -0
  53. simstack/models/base_lists.py +51 -0
  54. simstack/models/base_types.py +209 -0
  55. simstack/models/charts_artifact.py +690 -0
  56. simstack/models/dataset.py +451 -0
  57. simstack/models/dataset_metadata.py +390 -0
  58. simstack/models/datasettuple.py +587 -0
  59. simstack/models/file_instance.py +150 -0
  60. simstack/models/file_list.py +45 -0
  61. simstack/models/files.py +424 -0
  62. simstack/models/fire_and_forget_result.py +19 -0
  63. simstack/models/images2d.py +113 -0
  64. simstack/models/log_entry_model.py +37 -0
  65. simstack/models/models.py +52 -0
  66. simstack/models/named_data_reference.py +36 -0
  67. simstack/models/node_registry.py +96 -0
  68. simstack/models/pandas_model.py +239 -0
  69. simstack/models/parameters.py +402 -0
  70. simstack/models/pickle_models.py +300 -0
  71. simstack/models/project.py +13 -0
  72. simstack/models/resource_assignment.py +170 -0
  73. simstack/models/resource_definition.py +125 -0
  74. simstack/models/runner_model.py +39 -0
  75. simstack/models/simple_table.py +79 -0
  76. simstack/models/simstack_model.py +97 -0
  77. simstack/models/slurm_info.py +17 -0
  78. simstack/models/table_artifact.py +87 -0
  79. simstack/models/tag.py +12 -0
  80. simstack/models/unused_test_file.py +5 -0
  81. simstack/simstack_marker.com +1 -0
  82. simstack/static/docs/.buildinfo +4 -0
  83. simstack/static/docs/_images/GUI Concept.webp +0 -0
  84. simstack/static/docs/_modules/index.html +434 -0
  85. simstack/static/docs/_modules/simstack/core/artifacts.html +743 -0
  86. simstack/static/docs/_modules/simstack/core/asnyc_helper.html +330 -0
  87. simstack/static/docs/_modules/simstack/core/config_file.html +379 -0
  88. simstack/static/docs/_modules/simstack/core/definitions.html +341 -0
  89. simstack/static/docs/_modules/simstack/core/engine.html +437 -0
  90. simstack/static/docs/_modules/simstack/core/find_simstack_modules.html +360 -0
  91. simstack/static/docs/_modules/simstack/core/hash.html +528 -0
  92. simstack/static/docs/_modules/simstack/core/node.html +1392 -0
  93. simstack/static/docs/_modules/simstack/core/node_claim.html +347 -0
  94. simstack/static/docs/_modules/simstack/core/node_runner.html +711 -0
  95. simstack/static/docs/_modules/simstack/core/process_results.html +418 -0
  96. simstack/static/docs/_modules/simstack/core/recompute_artifacts.html +433 -0
  97. simstack/static/docs/_modules/simstack/core/reset_db.html +328 -0
  98. simstack/static/docs/_modules/simstack/core/resource_assignment.html +553 -0
  99. simstack/static/docs/_modules/simstack/core/resources.html +424 -0
  100. simstack/static/docs/_modules/simstack/core/route_table.html +349 -0
  101. simstack/static/docs/_modules/simstack/core/run_docker.html +425 -0
  102. simstack/static/docs/_modules/simstack/core/run_node.html +390 -0
  103. simstack/static/docs/_modules/simstack/core/runner.html +491 -0
  104. simstack/static/docs/_modules/simstack/core/services/base_service.html +522 -0
  105. simstack/static/docs/_modules/simstack/core/services/file_transfer_service.html +436 -0
  106. simstack/static/docs/_modules/simstack/core/services/git_restart_service.html +331 -0
  107. simstack/static/docs/_modules/simstack/core/services/git_uv_update_service.html +427 -0
  108. simstack/static/docs/_modules/simstack/core/services/node_execution_service.html +507 -0
  109. simstack/static/docs/_modules/simstack/core/services/resource_branch_monitor_service.html +390 -0
  110. simstack/static/docs/_modules/simstack/core/services/runner_cleanup_service.html +468 -0
  111. simstack/static/docs/_modules/simstack/core/services/runner_manager.html +485 -0
  112. simstack/static/docs/_modules/simstack/core/services/runner_status_service.html +329 -0
  113. simstack/static/docs/_modules/simstack/core/services/slurm_status_service.html +386 -0
  114. simstack/static/docs/_modules/simstack/core/services/stop_check_service.html +346 -0
  115. simstack/static/docs/_modules/simstack/core/services/timeout_restart_service.html +345 -0
  116. simstack/static/docs/_modules/simstack/core/simstack_result.html +355 -0
  117. simstack/static/docs/_modules/simstack/core/submit_node.html +536 -0
  118. simstack/static/docs/_modules/simstack/core/task_id.html +344 -0
  119. simstack/static/docs/_modules/simstack/methods/archive_files.html +598 -0
  120. simstack/static/docs/_modules/simstack/methods/fire_and_forget_runner.html +432 -0
  121. simstack/static/docs/_modules/simstack/methods/generate_test.html +443 -0
  122. simstack/static/docs/_modules/simstack/methods/get_file.html +342 -0
  123. simstack/static/docs/_modules/simstack/methods/mass_runner.html +476 -0
  124. simstack/static/docs/_modules/simstack/methods/multiple_executor.html +674 -0
  125. simstack/static/docs/_modules/simstack/methods/switch_git.html +332 -0
  126. simstack/static/docs/_modules/simstack/methods/upload_helpers.html +403 -0
  127. simstack/static/docs/_modules/simstack/models/array_list.html +337 -0
  128. simstack/static/docs/_modules/simstack/models/array_storage.html +417 -0
  129. simstack/static/docs/_modules/simstack/models/base_lists.html +374 -0
  130. simstack/static/docs/_modules/simstack/models/base_types.html +588 -0
  131. simstack/static/docs/_modules/simstack/models/charts_artifact.html +1035 -0
  132. simstack/static/docs/_modules/simstack/models/dataset.html +866 -0
  133. simstack/static/docs/_modules/simstack/models/dataset_metadata.html +711 -0
  134. simstack/static/docs/_modules/simstack/models/datasettuple.html +1005 -0
  135. simstack/static/docs/_modules/simstack/models/file_instance.html +472 -0
  136. simstack/static/docs/_modules/simstack/models/file_list.html +367 -0
  137. simstack/static/docs/_modules/simstack/models/files.html +773 -0
  138. simstack/static/docs/_modules/simstack/models/fire_and_forget_result.html +335 -0
  139. simstack/static/docs/_modules/simstack/models/images2d.html +447 -0
  140. simstack/static/docs/_modules/simstack/models/log_entry_model.html +356 -0
  141. simstack/static/docs/_modules/simstack/models/models.html +374 -0
  142. simstack/static/docs/_modules/simstack/models/named_data_reference.html +355 -0
  143. simstack/static/docs/_modules/simstack/models/node_registry.html +415 -0
  144. simstack/static/docs/_modules/simstack/models/pandas_model.html +570 -0
  145. simstack/static/docs/_modules/simstack/models/parameters.html +739 -0
  146. simstack/static/docs/_modules/simstack/models/pickle_models.html +631 -0
  147. simstack/static/docs/_modules/simstack/models/project.html +329 -0
  148. simstack/static/docs/_modules/simstack/models/resource_assignment.html +501 -0
  149. simstack/static/docs/_modules/simstack/models/resource_definition.html +477 -0
  150. simstack/static/docs/_modules/simstack/models/runner_model.html +361 -0
  151. simstack/static/docs/_modules/simstack/models/simple_table.html +413 -0
  152. simstack/static/docs/_modules/simstack/models/simstack_model.html +416 -0
  153. simstack/static/docs/_modules/simstack/models/slurm_info.html +333 -0
  154. simstack/static/docs/_modules/simstack/models/table_artifact.html +406 -0
  155. simstack/static/docs/_modules/simstack/models/tag.html +328 -0
  156. simstack/static/docs/_modules/simstack/tables/model_table.html +519 -0
  157. simstack/static/docs/_modules/simstack/tables/node_children.html +538 -0
  158. simstack/static/docs/_modules/simstack/tables/node_table.html +854 -0
  159. simstack/static/docs/_modules/simstack/tables/table_builder.html +642 -0
  160. simstack/static/docs/_modules/simstack/util/async_zip_utils.html +337 -0
  161. simstack/static/docs/_modules/simstack/util/b64mixin.html +339 -0
  162. simstack/static/docs/_modules/simstack/util/cleaned_json_schema.html +336 -0
  163. simstack/static/docs/_modules/simstack/util/config_reader.html +498 -0
  164. simstack/static/docs/_modules/simstack/util/custom_model_dump.html +391 -0
  165. simstack/static/docs/_modules/simstack/util/database_information.html +488 -0
  166. simstack/static/docs/_modules/simstack/util/db.html +1392 -0
  167. simstack/static/docs/_modules/simstack/util/db_logger.html +448 -0
  168. simstack/static/docs/_modules/simstack/util/default_from_dict.html +376 -0
  169. simstack/static/docs/_modules/simstack/util/directory_iterator.html +553 -0
  170. simstack/static/docs/_modules/simstack/util/docstring_parser.html +526 -0
  171. simstack/static/docs/_modules/simstack/util/file_hashing.html +394 -0
  172. simstack/static/docs/_modules/simstack/util/file_transfer_client.html +791 -0
  173. simstack/static/docs/_modules/simstack/util/files.html +733 -0
  174. simstack/static/docs/_modules/simstack/util/find_python_files.html +349 -0
  175. simstack/static/docs/_modules/simstack/util/generate_ui_schema.html +396 -0
  176. simstack/static/docs/_modules/simstack/util/generic_list_mixin.html +487 -0
  177. simstack/static/docs/_modules/simstack/util/get_module_path.html +336 -0
  178. simstack/static/docs/_modules/simstack/util/git_pull.html +381 -0
  179. simstack/static/docs/_modules/simstack/util/git_repository_status.html +411 -0
  180. simstack/static/docs/_modules/simstack/util/import_module.html +377 -0
  181. simstack/static/docs/_modules/simstack/util/importer.html +637 -0
  182. simstack/static/docs/_modules/simstack/util/init_data_source.html +357 -0
  183. simstack/static/docs/_modules/simstack/util/make_graph.html +423 -0
  184. simstack/static/docs/_modules/simstack/util/make_table.html +1171 -0
  185. simstack/static/docs/_modules/simstack/util/mappings.html +378 -0
  186. simstack/static/docs/_modules/simstack/util/minimal_route_finder.html +388 -0
  187. simstack/static/docs/_modules/simstack/util/mock_db.html +472 -0
  188. simstack/static/docs/_modules/simstack/util/module_path_checker.html +354 -0
  189. simstack/static/docs/_modules/simstack/util/object_list_mixin.html +649 -0
  190. simstack/static/docs/_modules/simstack/util/path_manager.html +566 -0
  191. simstack/static/docs/_modules/simstack/util/project_root_finder.html +357 -0
  192. simstack/static/docs/_modules/simstack/util/queue_watcher.html +593 -0
  193. simstack/static/docs/_modules/simstack/util/resource_config.html +532 -0
  194. simstack/static/docs/_modules/simstack/util/route_finder.html +390 -0
  195. simstack/static/docs/_modules/simstack/util/runner_util.html +487 -0
  196. simstack/static/docs/_modules/simstack/util/runner_utils.html +468 -0
  197. simstack/static/docs/_modules/simstack/util/safe_code_executor.html +510 -0
  198. simstack/static/docs/_modules/simstack/util/sample_config.html +414 -0
  199. simstack/static/docs/_modules/simstack/util/sensitive_content_filter.html +364 -0
  200. simstack/static/docs/_modules/simstack/util/setup_logging.html +365 -0
  201. simstack/static/docs/_modules/simstack/util/submit_to_watchdog.html +425 -0
  202. simstack/static/docs/_modules/simstack/util/toml_reader.html +482 -0
  203. simstack/static/docs/_modules/simstack/util/transform_file_name.html +357 -0
  204. simstack/static/docs/_modules/simstack/util/ui_tools.html +541 -0
  205. simstack/static/docs/_sources/architecture.rst.txt +25 -0
  206. simstack/static/docs/_sources/array_lists.rst.txt +60 -0
  207. simstack/static/docs/_sources/ci_pipeline.rst.txt +34 -0
  208. simstack/static/docs/_sources/data.rst.txt +175 -0
  209. simstack/static/docs/_sources/database_migrations.rst.txt +310 -0
  210. simstack/static/docs/_sources/datasets.rst.txt +93 -0
  211. simstack/static/docs/_sources/developer_guide.rst.txt +25 -0
  212. simstack/static/docs/_sources/docker_nodes.rst.txt +149 -0
  213. simstack/static/docs/_sources/files.rst.txt +159 -0
  214. simstack/static/docs/_sources/fire_and_forget_runner.rst.txt +67 -0
  215. simstack/static/docs/_sources/index.rst.txt +25 -0
  216. simstack/static/docs/_sources/installation.rst.txt +213 -0
  217. simstack/static/docs/_sources/lists.rst.txt +111 -0
  218. simstack/static/docs/_sources/mass_runner.rst.txt +91 -0
  219. simstack/static/docs/_sources/misc.rst.txt +106 -0
  220. simstack/static/docs/_sources/overview.rst.txt +91 -0
  221. simstack/static/docs/_sources/recovery.rst.txt +38 -0
  222. simstack/static/docs/_sources/resource_config.rst.txt +141 -0
  223. simstack/static/docs/_sources/simstack/modules/modules.rst.txt +7 -0
  224. simstack/static/docs/_sources/simstack/modules/simstack.core.rst.txt +205 -0
  225. simstack/static/docs/_sources/simstack/modules/simstack.core.services.rst.txt +109 -0
  226. simstack/static/docs/_sources/simstack/modules/simstack.methods.rst.txt +77 -0
  227. simstack/static/docs/_sources/simstack/modules/simstack.models.rst.txt +261 -0
  228. simstack/static/docs/_sources/simstack/modules/simstack.rst.txt +22 -0
  229. simstack/static/docs/_sources/simstack/modules/simstack.tables.rst.txt +45 -0
  230. simstack/static/docs/_sources/simstack/modules/simstack.util.rst.txt +381 -0
  231. simstack/static/docs/_sources/submit.rst.txt +141 -0
  232. simstack/static/docs/_sources/tables.rst.txt +50 -0
  233. simstack/static/docs/_sources/testing_complex_nodes.rst.txt +92 -0
  234. simstack/static/docs/_sources/ui_documentation.rst.txt +272 -0
  235. simstack/static/docs/_sources/workflows.rst.txt +446 -0
  236. simstack/static/docs/_static/base-stemmer.js +476 -0
  237. simstack/static/docs/_static/basic.css +906 -0
  238. simstack/static/docs/_static/cobalt2-theme.css +1 -0
  239. simstack/static/docs/_static/debug.css +69 -0
  240. simstack/static/docs/_static/docs-build-badge.css +51 -0
  241. simstack/static/docs/_static/docs-build-badge.js +51 -0
  242. simstack/static/docs/_static/doctools.js +150 -0
  243. simstack/static/docs/_static/documentation_options.js +13 -0
  244. simstack/static/docs/_static/english-stemmer.js +1066 -0
  245. simstack/static/docs/_static/file.png +0 -0
  246. simstack/static/docs/_static/language_data.js +13 -0
  247. simstack/static/docs/_static/minus.png +0 -0
  248. simstack/static/docs/_static/plus.png +0 -0
  249. simstack/static/docs/_static/pygments.css +250 -0
  250. simstack/static/docs/_static/scripts/furo-extensions.js +0 -0
  251. simstack/static/docs/_static/scripts/furo.js +3 -0
  252. simstack/static/docs/_static/scripts/furo.js.LICENSE.txt +7 -0
  253. simstack/static/docs/_static/scripts/furo.js.map +1 -0
  254. simstack/static/docs/_static/searchtools.js +693 -0
  255. simstack/static/docs/_static/skeleton.css +296 -0
  256. simstack/static/docs/_static/sphinx_highlight.js +159 -0
  257. simstack/static/docs/_static/styles/furo-extensions.css +2 -0
  258. simstack/static/docs/_static/styles/furo-extensions.css.map +1 -0
  259. simstack/static/docs/_static/styles/furo.css +2 -0
  260. simstack/static/docs/_static/styles/furo.css.map +1 -0
  261. simstack/static/docs/architecture.html +340 -0
  262. simstack/static/docs/array_lists.html +678 -0
  263. simstack/static/docs/ci_pipeline.html +385 -0
  264. simstack/static/docs/data.html +545 -0
  265. simstack/static/docs/database_migrations.html +652 -0
  266. simstack/static/docs/datasets.html +1268 -0
  267. simstack/static/docs/developer_guide.html +359 -0
  268. simstack/static/docs/docker_nodes.html +503 -0
  269. simstack/static/docs/files.html +718 -0
  270. simstack/static/docs/fire_and_forget_runner.html +641 -0
  271. simstack/static/docs/genindex.html +6390 -0
  272. simstack/static/docs/index.html +516 -0
  273. simstack/static/docs/installation.html +553 -0
  274. simstack/static/docs/lists.html +478 -0
  275. simstack/static/docs/mass_runner.html +481 -0
  276. simstack/static/docs/misc.html +454 -0
  277. simstack/static/docs/objects.inv +0 -0
  278. simstack/static/docs/overview.html +469 -0
  279. simstack/static/docs/py-modindex.html +1111 -0
  280. simstack/static/docs/recovery.html +371 -0
  281. simstack/static/docs/resource_config.html +590 -0
  282. simstack/static/docs/search.html +327 -0
  283. simstack/static/docs/searchindex.js +1 -0
  284. simstack/static/docs/simstack/modules/modules.html +489 -0
  285. simstack/static/docs/simstack/modules/simstack.core.html +1883 -0
  286. simstack/static/docs/simstack/modules/simstack.core.services.html +698 -0
  287. simstack/static/docs/simstack/modules/simstack.html +3060 -0
  288. simstack/static/docs/simstack/modules/simstack.methods.html +1150 -0
  289. simstack/static/docs/simstack/modules/simstack.models.html +13113 -0
  290. simstack/static/docs/simstack/modules/simstack.tables.html +635 -0
  291. simstack/static/docs/simstack/modules/simstack.util.html +3320 -0
  292. simstack/static/docs/submit.html +487 -0
  293. simstack/static/docs/tables.html +539 -0
  294. simstack/static/docs/testing_complex_nodes.html +458 -0
  295. simstack/static/docs/ui_documentation.html +788 -0
  296. simstack/static/docs/workflows.html +766 -0
  297. simstack/tables/__init__.py +0 -0
  298. simstack/tables/model_table.py +191 -0
  299. simstack/tables/node_children.py +219 -0
  300. simstack/tables/node_table.py +517 -0
  301. simstack/tables/table_builder.py +314 -0
  302. simstack/util/__init__.py +0 -0
  303. simstack/util/async_zip_utils.py +18 -0
  304. simstack/util/b64mixin.py +23 -0
  305. simstack/util/cleaned_json_schema.py +20 -0
  306. simstack/util/config_reader.py +179 -0
  307. simstack/util/custom_model_dump.py +75 -0
  308. simstack/util/database_information.py +160 -0
  309. simstack/util/db.py +1013 -0
  310. simstack/util/db_logger.py +117 -0
  311. simstack/util/default_from_dict.py +57 -0
  312. simstack/util/directory_iterator.py +216 -0
  313. simstack/util/docstring_parser.py +186 -0
  314. simstack/util/file_hashing.py +72 -0
  315. simstack/util/file_transfer_client.py +427 -0
  316. simstack/util/files.py +396 -0
  317. simstack/util/find_python_files.py +33 -0
  318. simstack/util/generate_ui_schema.py +80 -0
  319. simstack/util/generic_list_mixin.py +120 -0
  320. simstack/util/geometry_utils.py +118 -0
  321. simstack/util/get_module_path.py +20 -0
  322. simstack/util/git_pull.py +65 -0
  323. simstack/util/git_repository_status.py +95 -0
  324. simstack/util/import_module.py +63 -0
  325. simstack/util/importer.py +312 -0
  326. simstack/util/init_data_source.py +41 -0
  327. simstack/util/make_graph.py +107 -0
  328. simstack/util/make_table.py +837 -0
  329. simstack/util/mappings.py +41 -0
  330. simstack/util/minimal_route_finder.py +72 -0
  331. simstack/util/mock_db.py +144 -0
  332. simstack/util/module_path_checker.py +38 -0
  333. simstack/util/object_list_mixin.py +282 -0
  334. simstack/util/path_manager.py +223 -0
  335. simstack/util/project_root_finder.py +41 -0
  336. simstack/util/queue_watcher.py +262 -0
  337. simstack/util/resource_config.py +198 -0
  338. simstack/util/route_finder.py +74 -0
  339. simstack/util/runner_util.py +166 -0
  340. simstack/util/runner_utils.py +143 -0
  341. simstack/util/safe_code_executor.py +194 -0
  342. simstack/util/sample_config.py +98 -0
  343. simstack/util/sensitive_content_filter.py +48 -0
  344. simstack/util/setup_logging.py +49 -0
  345. simstack/util/submit_to_watchdog.py +106 -0
  346. simstack/util/toml_reader.py +142 -0
  347. simstack/util/transform_file_name.py +41 -0
  348. simstack/util/ui_tools.py +213 -0
  349. simstack-2.0.1.dist-info/METADATA +454 -0
  350. simstack-2.0.1.dist-info/RECORD +354 -0
  351. simstack-2.0.1.dist-info/WHEEL +5 -0
  352. simstack-2.0.1.dist-info/entry_points.txt +12 -0
  353. simstack-2.0.1.dist-info/licenses/LICENSE +21 -0
  354. simstack-2.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1392 @@
1
+ <!doctype html>
2
+ <html class="no-js" lang="en" data-content_root="../../../">
3
+ <head><meta charset="utf-8">
4
+ <meta name="viewport" content="width=device-width,initial-scale=1">
5
+ <meta name="color-scheme" content="light dark"><link rel="index" title="Index" href="../../../genindex.html"><link rel="search" title="Search" href="../../../search.html">
6
+
7
+ <!-- Generated with Sphinx 9.1.0 and Furo 2025.12.19 -->
8
+ <title>simstack.core.node - SimStack II documentation</title>
9
+ <link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=d111a655" />
10
+ <link rel="stylesheet" type="text/css" href="../../../_static/styles/furo.css?v=7bdb33bb" />
11
+ <link rel="stylesheet" type="text/css" href="../../../_static/styles/furo-extensions.css?v=8dab3a3b" />
12
+ <link rel="stylesheet" type="text/css" href="../../../_static/cobalt2-theme.css?v=2d651046" />
13
+ <link rel="stylesheet" type="text/css" href="../../../_static/docs-build-badge.css?v=803faff8" />
14
+
15
+
16
+
17
+
18
+ <style>
19
+ body {
20
+ --color-code-background: #f2f2f2;
21
+ --color-code-foreground: #1e1e1e;
22
+
23
+ }
24
+ @media not print {
25
+ body[data-theme="dark"] {
26
+ --color-code-background: #202020;
27
+ --color-code-foreground: #d0d0d0;
28
+ --color-background-primary: #132738;
29
+ --color-background-secondary: #1e3a52;
30
+ --color-foreground-primary: #ffffff;
31
+ --color-foreground-secondary: #bac8d3;
32
+ --color-brand-primary: #22d5ff;
33
+ --color-brand-content: #0088ff;
34
+
35
+ }
36
+ @media (prefers-color-scheme: dark) {
37
+ body:not([data-theme="light"]) {
38
+ --color-code-background: #202020;
39
+ --color-code-foreground: #d0d0d0;
40
+ --color-background-primary: #132738;
41
+ --color-background-secondary: #1e3a52;
42
+ --color-foreground-primary: #ffffff;
43
+ --color-foreground-secondary: #bac8d3;
44
+ --color-brand-primary: #22d5ff;
45
+ --color-brand-content: #0088ff;
46
+
47
+ }
48
+ }
49
+ }
50
+ </style></head>
51
+ <body>
52
+
53
+ <script>
54
+ document.body.dataset.theme = localStorage.getItem("theme") || "auto";
55
+ </script>
56
+
57
+
58
+ <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
59
+ <symbol id="svg-toc" viewBox="0 0 24 24">
60
+ <title>Contents</title>
61
+ <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
62
+ <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
63
+ </svg>
64
+ </symbol>
65
+ <symbol id="svg-menu" viewBox="0 0 24 24">
66
+ <title>Menu</title>
67
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
68
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
69
+ <line x1="3" y1="12" x2="21" y2="12"></line>
70
+ <line x1="3" y1="6" x2="21" y2="6"></line>
71
+ <line x1="3" y1="18" x2="21" y2="18"></line>
72
+ </svg>
73
+ </symbol>
74
+ <symbol id="svg-arrow-right" viewBox="0 0 24 24">
75
+ <title>Expand</title>
76
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
77
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
78
+ <polyline points="9 18 15 12 9 6"></polyline>
79
+ </svg>
80
+ </symbol>
81
+ <symbol id="svg-sun" viewBox="0 0 24 24">
82
+ <title>Light mode</title>
83
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
84
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
85
+ <circle cx="12" cy="12" r="5"></circle>
86
+ <line x1="12" y1="1" x2="12" y2="3"></line>
87
+ <line x1="12" y1="21" x2="12" y2="23"></line>
88
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
89
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
90
+ <line x1="1" y1="12" x2="3" y2="12"></line>
91
+ <line x1="21" y1="12" x2="23" y2="12"></line>
92
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
93
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
94
+ </svg>
95
+ </symbol>
96
+ <symbol id="svg-moon" viewBox="0 0 24 24">
97
+ <title>Dark mode</title>
98
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
99
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
100
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
101
+ <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
102
+ </svg>
103
+ </symbol>
104
+ <symbol id="svg-sun-with-moon" viewBox="0 0 24 24">
105
+ <title>Auto light/dark, in light mode</title>
106
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
107
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round"
108
+ class="icon-custom-derived-from-feather-sun-and-tabler-moon">
109
+ <path style="opacity: 50%" d="M 5.411 14.504 C 5.471 14.504 5.532 14.504 5.591 14.504 C 3.639 16.319 4.383 19.569 6.931 20.352 C 7.693 20.586 8.512 20.551 9.25 20.252 C 8.023 23.207 4.056 23.725 2.11 21.184 C 0.166 18.642 1.702 14.949 4.874 14.536 C 5.051 14.512 5.231 14.5 5.411 14.5 L 5.411 14.504 Z"/>
110
+ <line x1="14.5" y1="3.25" x2="14.5" y2="1.25"/>
111
+ <line x1="14.5" y1="15.85" x2="14.5" y2="17.85"/>
112
+ <line x1="10.044" y1="5.094" x2="8.63" y2="3.68"/>
113
+ <line x1="19" y1="14.05" x2="20.414" y2="15.464"/>
114
+ <line x1="8.2" y1="9.55" x2="6.2" y2="9.55"/>
115
+ <line x1="20.8" y1="9.55" x2="22.8" y2="9.55"/>
116
+ <line x1="10.044" y1="14.006" x2="8.63" y2="15.42"/>
117
+ <line x1="19" y1="5.05" x2="20.414" y2="3.636"/>
118
+ <circle cx="14.5" cy="9.55" r="3.6"/>
119
+ </svg>
120
+ </symbol>
121
+ <symbol id="svg-moon-with-sun" viewBox="0 0 24 24">
122
+ <title>Auto light/dark, in dark mode</title>
123
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
124
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round"
125
+ class="icon-custom-derived-from-feather-sun-and-tabler-moon">
126
+ <path d="M 8.282 7.007 C 8.385 7.007 8.494 7.007 8.595 7.007 C 5.18 10.184 6.481 15.869 10.942 17.24 C 12.275 17.648 13.706 17.589 15 17.066 C 12.851 22.236 5.91 23.143 2.505 18.696 C -0.897 14.249 1.791 7.786 7.342 7.063 C 7.652 7.021 7.965 7 8.282 7 L 8.282 7.007 Z"/>
127
+ <line style="opacity: 50%" x1="18" y1="3.705" x2="18" y2="2.5"/>
128
+ <line style="opacity: 50%" x1="18" y1="11.295" x2="18" y2="12.5"/>
129
+ <line style="opacity: 50%" x1="15.316" y1="4.816" x2="14.464" y2="3.964"/>
130
+ <line style="opacity: 50%" x1="20.711" y1="10.212" x2="21.563" y2="11.063"/>
131
+ <line style="opacity: 50%" x1="14.205" y1="7.5" x2="13.001" y2="7.5"/>
132
+ <line style="opacity: 50%" x1="21.795" y1="7.5" x2="23" y2="7.5"/>
133
+ <line style="opacity: 50%" x1="15.316" y1="10.184" x2="14.464" y2="11.036"/>
134
+ <line style="opacity: 50%" x1="20.711" y1="4.789" x2="21.563" y2="3.937"/>
135
+ <circle style="opacity: 50%" cx="18" cy="7.5" r="2.169"/>
136
+ </svg>
137
+ </symbol>
138
+ <symbol id="svg-pencil" viewBox="0 0 24 24">
139
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
140
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-pencil-code">
141
+ <path d="M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4" />
142
+ <path d="M13.5 6.5l4 4" />
143
+ <path d="M20 21l2 -2l-2 -2" />
144
+ <path d="M17 17l-2 2l2 2" />
145
+ </svg>
146
+ </symbol>
147
+ <symbol id="svg-eye" viewBox="0 0 24 24">
148
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
149
+ stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-eye-code">
150
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
151
+ <path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
152
+ <path
153
+ d="M11.11 17.958c-3.209 -.307 -5.91 -2.293 -8.11 -5.958c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6c-.21 .352 -.427 .688 -.647 1.008" />
154
+ <path d="M20 21l2 -2l-2 -2" />
155
+ <path d="M17 17l-2 2l2 2" />
156
+ </svg>
157
+ </symbol>
158
+ </svg>
159
+
160
+ <input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation" aria-label="Toggle site navigation sidebar">
161
+ <input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc" aria-label="Toggle table of contents sidebar">
162
+ <label class="overlay sidebar-overlay" for="__navigation"></label>
163
+ <label class="overlay toc-overlay" for="__toc"></label>
164
+
165
+ <a class="skip-to-content muted-link" href="#furo-main-content">Skip to content</a>
166
+
167
+
168
+
169
+ <div class="page">
170
+ <header class="mobile-header">
171
+ <div class="header-left">
172
+ <label class="nav-overlay-icon" for="__navigation">
173
+ <span class="icon"><svg><use href="#svg-menu"></use></svg></span>
174
+ </label>
175
+ </div>
176
+ <div class="header-center">
177
+ <a href="../../../index.html"><div class="brand">SimStack II documentation</div></a>
178
+ </div>
179
+ <div class="header-right">
180
+ <div class="theme-toggle-container theme-toggle-header">
181
+ <button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
182
+ <svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
183
+ <svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
184
+ <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
185
+ <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
186
+ </button>
187
+ </div>
188
+ <label class="toc-overlay-icon toc-header-icon no-toc" for="__toc">
189
+ <span class="icon"><svg><use href="#svg-toc"></use></svg></span>
190
+ </label>
191
+ </div>
192
+ </header>
193
+ <aside class="sidebar-drawer">
194
+ <div class="sidebar-container">
195
+
196
+ <div class="sidebar-sticky"><a class="sidebar-brand" href="../../../index.html">
197
+
198
+
199
+ </a><form class="sidebar-search-container" method="get" action="../../../search.html" role="search">
200
+ <input class="sidebar-search" placeholder="Search" name="q" aria-label="Search">
201
+ <input type="hidden" name="check_keywords" value="yes">
202
+ <input type="hidden" name="area" value="default">
203
+ </form>
204
+ <div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
205
+ <p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
206
+ <ul>
207
+ <li class="toctree-l1"><a class="reference internal" href="../../../overview.html">Overview</a></li>
208
+ <li class="toctree-l1"><a class="reference internal" href="../../../workflows.html">Workflows</a></li>
209
+ <li class="toctree-l1"><a class="reference internal" href="../../../ui_documentation.html">Graphical User Interface</a></li>
210
+ <li class="toctree-l1 has-children"><a class="reference internal" href="../../../developer_guide.html">Developer Guide</a><input aria-label="Toggle navigation of Developer Guide" class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" role="switch" type="checkbox"/><label for="toctree-checkbox-1"><span class="icon"><svg><use href="#svg-arrow-right"></use></svg></span></label><ul>
211
+ <li class="toctree-l2"><a class="reference internal" href="../../../data.html">Persisting and Visualizing Data</a></li>
212
+ <li class="toctree-l2"><a class="reference internal" href="../../../datasets.html">Datasets</a></li>
213
+ <li class="toctree-l2"><a class="reference internal" href="../../../lists.html">List Mixins</a></li>
214
+ <li class="toctree-l2"><a class="reference internal" href="../../../array_lists.html">Array Lists</a></li>
215
+ <li class="toctree-l2"><a class="reference internal" href="../../../tables.html">Tables</a></li>
216
+ <li class="toctree-l2"><a class="reference internal" href="../../../files.html">File Management</a></li>
217
+ <li class="toctree-l2"><a class="reference internal" href="../../../resource_config.html">Program Execution</a></li>
218
+ <li class="toctree-l2"><a class="reference internal" href="../../../mass_runner.html">MassRunner</a></li>
219
+ <li class="toctree-l2"><a class="reference internal" href="../../../fire_and_forget_runner.html">FireAndForgetRunner</a></li>
220
+ <li class="toctree-l2"><a class="reference internal" href="../../../docker_nodes.html">Creating Docker Containers for SimStack Nodes</a></li>
221
+ <li class="toctree-l2"><a class="reference internal" href="../../../testing_complex_nodes.html">Testing Complex Nodes</a></li>
222
+ <li class="toctree-l2"><a class="reference internal" href="../../../database_migrations.html">Database Migrations</a></li>
223
+ <li class="toctree-l2"><a class="reference internal" href="../../../ci_pipeline.html">CI Pipeline and Documentation Artifacts</a></li>
224
+ <li class="toctree-l2"><a class="reference internal" href="../../../misc.html">Miscellaneous</a></li>
225
+ </ul>
226
+ </li>
227
+ <li class="toctree-l1"><a class="reference internal" href="../../../installation.html">Simstack II Setup</a></li>
228
+ <li class="toctree-l1 has-children"><a class="reference internal" href="../../../simstack/modules/modules.html">simstack</a><input aria-label="Toggle navigation of simstack" class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" role="switch" type="checkbox"/><label for="toctree-checkbox-2"><span class="icon"><svg><use href="#svg-arrow-right"></use></svg></span></label><ul>
229
+ <li class="toctree-l2 has-children"><a class="reference internal" href="../../../simstack/modules/simstack.html">simstack package</a><input aria-label="Toggle navigation of simstack package" class="toctree-checkbox" id="toctree-checkbox-3" name="toctree-checkbox-3" role="switch" type="checkbox"/><label for="toctree-checkbox-3"><span class="icon"><svg><use href="#svg-arrow-right"></use></svg></span></label><ul>
230
+ <li class="toctree-l3 has-children"><a class="reference internal" href="../../../simstack/modules/simstack.core.html">simstack.core package</a><input aria-label="Toggle navigation of simstack.core package" class="toctree-checkbox" id="toctree-checkbox-4" name="toctree-checkbox-4" role="switch" type="checkbox"/><label for="toctree-checkbox-4"><span class="icon"><svg><use href="#svg-arrow-right"></use></svg></span></label><ul>
231
+ <li class="toctree-l4"><a class="reference internal" href="../../../simstack/modules/simstack.core.services.html">simstack.core.services package</a></li>
232
+ </ul>
233
+ </li>
234
+ <li class="toctree-l3"><a class="reference internal" href="../../../simstack/modules/simstack.methods.html">simstack.methods package</a></li>
235
+ <li class="toctree-l3"><a class="reference internal" href="../../../simstack/modules/simstack.models.html">simstack.models package</a></li>
236
+ <li class="toctree-l3"><a class="reference internal" href="../../../simstack/modules/simstack.tables.html">simstack.tables package</a></li>
237
+ <li class="toctree-l3"><a class="reference internal" href="../../../simstack/modules/simstack.util.html">simstack.util package</a></li>
238
+ </ul>
239
+ </li>
240
+ </ul>
241
+ </li>
242
+ </ul>
243
+
244
+ </div>
245
+ </div>
246
+
247
+ </div>
248
+
249
+ </div>
250
+ </aside>
251
+ <div class="main">
252
+ <div class="content">
253
+ <div class="article-container">
254
+ <a href="#" class="back-to-top muted-link">
255
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
256
+ <path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
257
+ </svg>
258
+ <span>Back to top</span>
259
+ </a>
260
+ <div class="content-icon-container">
261
+ <div class="theme-toggle-container theme-toggle-content">
262
+ <button class="theme-toggle" aria-label="Toggle Light / Dark / Auto color theme">
263
+ <svg class="theme-icon-when-auto-light"><use href="#svg-sun-with-moon"></use></svg>
264
+ <svg class="theme-icon-when-auto-dark"><use href="#svg-moon-with-sun"></use></svg>
265
+ <svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
266
+ <svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
267
+ </button>
268
+ </div>
269
+ <label class="toc-overlay-icon toc-content-icon no-toc" for="__toc">
270
+ <span class="icon"><svg><use href="#svg-toc"></use></svg></span>
271
+ </label>
272
+ </div>
273
+ <article role="main" id="furo-main-content">
274
+ <h1>Source code for simstack.core.node</h1><div class="highlight"><pre>
275
+ <span></span><span class="kn">import</span><span class="w"> </span><span class="nn">asyncio</span>
276
+ <span class="kn">import</span><span class="w"> </span><span class="nn">functools</span>
277
+ <span class="kn">import</span><span class="w"> </span><span class="nn">inspect</span>
278
+ <span class="kn">import</span><span class="w"> </span><span class="nn">logging</span>
279
+ <span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
280
+ <span class="kn">from</span><span class="w"> </span><span class="nn">datetime</span><span class="w"> </span><span class="kn">import</span> <span class="n">datetime</span>
281
+ <span class="kn">from</span><span class="w"> </span><span class="nn">pathlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">Path</span>
282
+ <span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
283
+ <span class="n">Any</span><span class="p">,</span>
284
+ <span class="n">Callable</span><span class="p">,</span>
285
+ <span class="n">Optional</span><span class="p">,</span>
286
+ <span class="n">TypeVar</span><span class="p">,</span>
287
+ <span class="n">cast</span><span class="p">,</span>
288
+ <span class="n">List</span><span class="p">,</span>
289
+ <span class="n">ParamSpec</span><span class="p">,</span>
290
+ <span class="n">Union</span><span class="p">,</span>
291
+ <span class="n">overload</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">,</span>
292
+ <span class="p">)</span>
293
+
294
+ <span class="kn">import</span><span class="w"> </span><span class="nn">coolname</span> <span class="c1"># type: ignore[import-untyped]</span>
295
+ <span class="kn">import</span><span class="w"> </span><span class="nn">nest_asyncio</span> <span class="c1"># type: ignore[import-untyped]</span>
296
+ <span class="kn">from</span><span class="w"> </span><span class="nn">odmantic</span><span class="w"> </span><span class="kn">import</span> <span class="n">Model</span><span class="p">,</span> <span class="n">ObjectId</span>
297
+ <span class="kn">from</span><span class="w"> </span><span class="nn">pydantic</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseModel</span>
298
+
299
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.artifacts</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_artifacts</span><span class="p">,</span> <span class="n">ArtifactArguments</span>
300
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.context</span><span class="w"> </span><span class="kn">import</span> <span class="n">context</span>
301
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.definitions</span><span class="w"> </span><span class="kn">import</span> <span class="n">TaskStatus</span>
302
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.hash</span><span class="w"> </span><span class="kn">import</span> <span class="n">complex_hash_function</span>
303
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.node_claim</span><span class="w"> </span><span class="kn">import</span> <span class="n">claim_submitted_node</span>
304
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.node_runner</span><span class="w"> </span><span class="kn">import</span> <span class="n">NodeRunner</span>
305
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.process_results</span><span class="w"> </span><span class="kn">import</span> <span class="n">process_result_helper</span>
306
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.resource_assignment</span><span class="w"> </span><span class="kn">import</span> <span class="n">apply_resource_assignment_to_node_registry</span>
307
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.simstack_result</span><span class="w"> </span><span class="kn">import</span> <span class="n">SimstackResult</span>
308
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.task_id</span><span class="w"> </span><span class="kn">import</span> <span class="n">set_task_id</span><span class="p">,</span> <span class="n">clear_task_id</span>
309
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">ModelMapping</span><span class="p">,</span> <span class="n">Parameters</span><span class="p">,</span> <span class="n">Project</span>
310
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">NodeModel</span>
311
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">NodeRegistry</span><span class="p">,</span> <span class="n">NamedDataReference</span>
312
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models.file_list</span><span class="w"> </span><span class="kn">import</span> <span class="n">FileList</span>
313
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models.files</span><span class="w"> </span><span class="kn">import</span> <span class="n">FileStack</span>
314
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models.parameters</span><span class="w"> </span><span class="kn">import</span> <span class="n">Resource</span><span class="p">,</span> <span class="n">Queue</span>
315
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.models.simstack_model</span><span class="w"> </span><span class="kn">import</span> <span class="n">is_simstack_model</span>
316
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.util.importer</span><span class="w"> </span><span class="kn">import</span> <span class="n">import_function</span><span class="p">,</span> <span class="n">import_class</span>
317
+
318
+ <span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;Node&quot;</span><span class="p">)</span>
319
+
320
+ <span class="n">nest_asyncio</span><span class="o">.</span><span class="n">apply</span><span class="p">()</span>
321
+
322
+ <span class="n">T</span> <span class="o">=</span> <span class="n">TypeVar</span><span class="p">(</span><span class="s2">&quot;T&quot;</span><span class="p">)</span>
323
+
324
+
325
+ <div class="viewcode-block" id="default_name_generator">
326
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.default_name_generator">[docs]</a>
327
+ <span class="k">def</span><span class="w"> </span><span class="nf">default_name_generator</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
328
+ <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="s2">&quot;-&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">coolname</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="mi">2</span><span class="p">)))</span></div>
329
+
330
+
331
+
332
+ <div class="viewcode-block" id="hashable_value">
333
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.hashable_value">[docs]</a>
334
+ <span class="k">def</span><span class="w"> </span><span class="nf">hashable_value</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Any</span><span class="p">:</span>
335
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">BaseModel</span><span class="p">):</span>
336
+ <span class="k">return</span> <span class="n">hashable_inputs</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
337
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">list</span><span class="p">):</span>
338
+ <span class="k">return</span> <span class="p">[</span><span class="n">hashable_value</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">value</span><span class="p">]</span>
339
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
340
+ <span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">hashable_value</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">value</span><span class="p">)</span>
341
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
342
+ <span class="k">return</span> <span class="p">{</span><span class="n">key</span><span class="p">:</span> <span class="n">hashable_value</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">items</span><span class="p">()}</span>
343
+ <span class="k">return</span> <span class="n">value</span></div>
344
+
345
+
346
+
347
+ <div class="viewcode-block" id="hashable_inputs">
348
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.hashable_inputs">[docs]</a>
349
+ <span class="k">def</span><span class="w"> </span><span class="nf">hashable_inputs</span><span class="p">(</span><span class="n">arg</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]:</span>
350
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
351
+ <span class="sd"> Get the hashable inputs for the node. This allows exclusion of some fields from the hash.</span>
352
+
353
+ <span class="sd"> Returns:</span>
354
+ <span class="sd"> dict: The hashable inputs.</span>
355
+ <span class="sd"> &quot;&quot;&quot;</span>
356
+ <span class="k">return</span> <span class="p">{</span>
357
+ <span class="n">key</span><span class="p">:</span> <span class="n">hashable_value</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
358
+ <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">arg</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
359
+ <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s2">&quot;id&quot;</span><span class="p">]</span>
360
+ <span class="p">}</span></div>
361
+
362
+
363
+
364
+ <div class="viewcode-block" id="compute_arg_hash">
365
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.compute_arg_hash">[docs]</a>
366
+ <span class="k">def</span><span class="w"> </span><span class="nf">compute_arg_hash</span><span class="p">(</span><span class="n">args</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Model</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
367
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
368
+ <span class="sd"> Computes a hash for a list of arguments provided, where each argument</span>
369
+ <span class="sd"> is an instance of the Model class or can be processed into a hashable</span>
370
+ <span class="sd"> format. Uses a complex hashing function for the resulting computation.</span>
371
+
372
+ <span class="sd"> Args:</span>
373
+ <span class="sd"> args (List[Model]): A list of objects where each object must be an instance of the</span>
374
+ <span class="sd"> Model class. The objects are used to compute their respective</span>
375
+ <span class="sd"> hash values via a specified complex hashing mechanism.</span>
376
+
377
+ <span class="sd"> Returns:</span>
378
+ <span class="sd"> str: A string representation of the computed hash for the provided</span>
379
+ <span class="sd"> list of arguments.</span>
380
+
381
+ <span class="sd"> Raises:</span>
382
+ <span class="sd"> TypeError: If any item in the provided list is not an instance of the</span>
383
+ <span class="sd"> Model class.</span>
384
+ <span class="sd"> &quot;&quot;&quot;</span>
385
+ <span class="n">arg_hashes</span> <span class="o">=</span> <span class="p">[]</span>
386
+ <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
387
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">Model</span><span class="p">):</span>
388
+ <span class="n">arg_hash</span> <span class="o">=</span> <span class="p">(</span>
389
+ <span class="n">arg</span><span class="o">.</span><span class="n">complex_hash</span><span class="p">()</span>
390
+ <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="s2">&quot;complex_hash&quot;</span><span class="p">)</span>
391
+ <span class="k">else</span> <span class="n">complex_hash_function</span><span class="p">(</span><span class="n">hashable_inputs</span><span class="p">(</span><span class="n">arg</span><span class="p">))</span>
392
+ <span class="p">)</span>
393
+ <span class="n">arg_hashes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg_hash</span><span class="p">)</span>
394
+ <span class="k">else</span><span class="p">:</span>
395
+ <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Argument </span><span class="si">{</span><span class="n">arg</span><span class="si">}</span><span class="s2"> is not an instance of </span><span class="si">{</span><span class="n">Model</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
396
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">complex_hash_function</span><span class="p">(</span><span class="n">arg_hashes</span><span class="p">))</span></div>
397
+
398
+
399
+
400
+ <span class="k">def</span><span class="w"> </span><span class="nf">_parameters_field_values</span><span class="p">(</span><span class="n">parameters</span><span class="p">:</span> <span class="n">Parameters</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">]:</span>
401
+ <span class="n">raw_values</span> <span class="o">=</span> <span class="nb">object</span><span class="o">.</span><span class="fm">__getattribute__</span><span class="p">(</span><span class="n">parameters</span><span class="p">,</span> <span class="s2">&quot;__dict__&quot;</span><span class="p">)</span>
402
+ <span class="k">return</span> <span class="p">{</span>
403
+ <span class="n">field_name</span><span class="p">:</span> <span class="n">raw_values</span><span class="p">[</span><span class="n">field_name</span><span class="p">]</span>
404
+ <span class="k">for</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">Parameters</span><span class="o">.</span><span class="n">model_fields</span>
405
+ <span class="k">if</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">raw_values</span>
406
+ <span class="p">}</span>
407
+
408
+
409
+ <span class="k">def</span><span class="w"> </span><span class="nf">_parameters_from_node_kwargs</span><span class="p">(</span><span class="n">kwargs_node</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Parameters</span><span class="p">:</span>
410
+ <span class="n">base_parameters</span> <span class="o">=</span> <span class="n">kwargs_node</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;parameters&quot;</span><span class="p">)</span>
411
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">base_parameters</span><span class="p">,</span> <span class="n">Parameters</span><span class="p">):</span>
412
+ <span class="n">values</span> <span class="o">=</span> <span class="n">_parameters_field_values</span><span class="p">(</span><span class="n">base_parameters</span><span class="p">)</span>
413
+ <span class="k">elif</span> <span class="n">base_parameters</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
414
+ <span class="n">values</span> <span class="o">=</span> <span class="n">_parameters_field_values</span><span class="p">(</span><span class="n">Parameters</span><span class="p">())</span>
415
+ <span class="k">else</span><span class="p">:</span>
416
+ <span class="n">values</span> <span class="o">=</span> <span class="n">_parameters_field_values</span><span class="p">(</span><span class="n">Parameters</span><span class="o">.</span><span class="n">model_validate</span><span class="p">(</span><span class="n">base_parameters</span><span class="p">))</span>
417
+
418
+ <span class="k">for</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">Parameters</span><span class="o">.</span><span class="n">model_fields</span><span class="p">:</span>
419
+ <span class="k">if</span> <span class="n">field_name</span> <span class="ow">in</span> <span class="n">kwargs_node</span><span class="p">:</span>
420
+ <span class="n">values</span><span class="p">[</span><span class="n">field_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs_node</span><span class="p">[</span><span class="n">field_name</span><span class="p">]</span>
421
+
422
+ <span class="k">return</span> <span class="n">Parameters</span><span class="o">.</span><span class="n">model_validate</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
423
+
424
+
425
+ <div class="viewcode-block" id="Node">
426
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node">[docs]</a>
427
+ <span class="k">class</span><span class="w"> </span><span class="nc">Node</span><span class="p">:</span>
428
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
429
+ <span class="sd"> represents a computational task or node in the workflow, managing its lifecycle,</span>
430
+ <span class="sd"> execution environment, and interactions with the database. This class helps in</span>
431
+ <span class="sd"> defining tasks, storing their details, and ensuring they are executed either</span>
432
+ <span class="sd"> locally or remotely, with their statuses tracked within a shared database</span>
433
+ <span class="sd"> context.</span>
434
+
435
+ <span class="sd"> :ivar name: The name of the function associated with the node.</span>
436
+ <span class="sd"> :type name: str</span>
437
+ <span class="sd"> :ivar custom_name: A custom name for the node, generated if not specified.</span>
438
+ <span class="sd"> :type custom_name: str or None</span>
439
+ <span class="sd"> :ivar registry_entry: The registry entry associated with the node in the database.</span>
440
+ <span class="sd"> :type registry_entry: NodeRegistry or None</span>
441
+ <span class="sd"> :ivar parent_id: The parent node&#39;s unique identifier, if applicable.</span>
442
+ <span class="sd"> :type parent_id: ObjectId or None</span>
443
+ <span class="sd"> :ivar parameters: Additional parameters for the node.</span>
444
+ <span class="sd"> :type parameters: Parameters</span>
445
+ <span class="sd"> :ivar _func: The function represented by the node.</span>
446
+ <span class="sd"> :type _func: Callable[[Model], Model]</span>
447
+ <span class="sd"> &quot;&quot;&quot;</span>
448
+
449
+ <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
450
+ <span class="bp">self</span><span class="p">,</span>
451
+ <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span>
452
+ <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span>
453
+ <span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
454
+ <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
455
+
456
+ <span class="bp">self</span><span class="o">.</span><span class="n">_args</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="c1"># Convert to list to allow appending</span>
457
+
458
+ <span class="c1"># Extract specific known parameters</span>
459
+ <span class="bp">self</span><span class="o">.</span><span class="n">_func</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;func&quot;</span><span class="p">)</span>
460
+ <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_func</span><span class="o">.</span><span class="vm">__name__</span>
461
+ <span class="bp">self</span><span class="o">.</span><span class="n">is_async</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;is_async&quot;</span><span class="p">)</span>
462
+ <span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;parent_id&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
463
+ <span class="bp">self</span><span class="o">.</span><span class="n">call_path</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;call_path&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span> <span class="ow">or</span> <span class="s2">&quot;.&quot;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
464
+ <span class="bp">self</span><span class="o">.</span><span class="n">_arg_hash</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;arg_hash&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
465
+ <span class="bp">self</span><span class="o">.</span><span class="n">_function_hash</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;function_hash&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
466
+
467
+ <span class="c1"># Get function signature to identify argument names</span>
468
+ <span class="n">sig</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_func</span><span class="p">)</span>
469
+ <span class="n">param_names</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">sig</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
470
+
471
+ <span class="c1"># Move kwargs that match function parameter names to args</span>
472
+ <span class="k">for</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="n">param_names</span><span class="p">:</span>
473
+ <span class="k">if</span> <span class="n">param_name</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
474
+ <span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">param_name</span><span class="p">))</span>
475
+
476
+ <span class="k">if</span> <span class="s2">&quot;custom_name&quot;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
477
+ <span class="bp">self</span><span class="o">.</span><span class="n">custom_name</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;custom_name&quot;</span><span class="p">]</span> <span class="c1"># pass to children</span>
478
+ <span class="k">else</span><span class="p">:</span>
479
+ <span class="bp">self</span><span class="o">.</span><span class="n">custom_name</span> <span class="o">=</span> <span class="n">default_name_generator</span><span class="p">()</span>
480
+
481
+ <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;parameters&quot;</span><span class="p">)</span>
482
+ <span class="bp">self</span><span class="o">.</span><span class="n">recompute_artifacts</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;recompute_artifacts&quot;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span>
483
+ <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">recompute_artifacts</span> <span class="ow">or</span> <span class="kc">False</span>
484
+ <span class="p">)</span>
485
+
486
+ <span class="bp">self</span><span class="o">.</span><span class="n">_function_kwargs</span> <span class="o">=</span> <span class="p">(</span>
487
+ <span class="n">kwargs</span> <span class="c1"># what is left over here must be kwargs of the function</span>
488
+ <span class="p">)</span>
489
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">:</span> <span class="n">NodeRegistry</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span>
490
+
491
+ <span class="nd">@property</span>
492
+ <span class="k">def</span><span class="w"> </span><span class="nf">id</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ObjectId</span> <span class="o">|</span> <span class="kc">None</span><span class="p">:</span>
493
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
494
+ <span class="k">return</span> <span class="kc">None</span>
495
+ <span class="k">else</span><span class="p">:</span>
496
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span>
497
+
498
+ <span class="nd">@property</span>
499
+ <span class="k">def</span><span class="w"> </span><span class="nf">status</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">TaskStatus</span><span class="p">:</span>
500
+ <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">,</span> <span class="s2">&quot;status&quot;</span><span class="p">,</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">)</span>
501
+
502
+ <div class="viewcode-block" id="Node.make_registry_entry">
503
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.make_registry_entry">[docs]</a>
504
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">make_registry_entry</span><span class="p">(</span>
505
+ <span class="bp">self</span><span class="p">,</span> <span class="n">function_hash</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">arg_hash</span><span class="p">:</span> <span class="nb">str</span>
506
+ <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">NodeRegistry</span><span class="p">:</span>
507
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
508
+ <span class="sd"> Creates a registry entry for the node in the database.</span>
509
+
510
+ <span class="sd"> This method is used to create a new entry in the database for the node,</span>
511
+ <span class="sd"> including its inputs and outputs. It ensures that the task is properly</span>
512
+ <span class="sd"> registered with all necessary details.</span>
513
+
514
+ <span class="sd"> :rtype: NodeRegistry</span>
515
+ <span class="sd"> &quot;&quot;&quot;</span>
516
+ <span class="c1"># TODO why does this fail when nodemapping succeeds ?</span>
517
+ <span class="c1"># function_mapping = await context.db.find_one(NodeModel, NodeModel.name == self.name)</span>
518
+ <span class="n">function_mapping</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">node_mappings</span><span class="o">.</span><span class="n">get_by_name</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
519
+ <span class="k">if</span> <span class="n">function_mapping</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
520
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Could not find function mapping for name: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
521
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Could not find function mapping for name: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
522
+
523
+ <span class="n">input_references</span> <span class="o">=</span> <span class="p">[]</span>
524
+ <span class="c1"># Get function signature to identify argument names</span>
525
+ <span class="n">sig</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_func</span><span class="p">)</span>
526
+ <span class="n">param_names</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">sig</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
527
+
528
+ <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">arg</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="p">):</span>
529
+ <span class="c1"># if there is no table for an arg raise an error</span>
530
+ <span class="c1"># input_table_name = await context.db.find_one(ModelMapping, ModelMapping.name == arg.__class__.__name__)</span>
531
+ <span class="n">input_table_name</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">model_mappings</span><span class="o">.</span><span class="n">get_by_name</span><span class="p">(</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
532
+ <span class="k">if</span> <span class="n">input_table_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
533
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Could not find table name for </span><span class="si">{</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
534
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Could not find table name for </span><span class="si">{</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
535
+ <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">Model</span><span class="p">):</span>
536
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2"> is not an odmantic Model&quot;</span><span class="p">)</span>
537
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2"> is not an odmantic Model&quot;</span><span class="p">)</span>
538
+
539
+ <span class="n">argument_entry</span> <span class="o">=</span> <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
540
+
541
+ <span class="c1"># Check if the save operation was successful and returned a valid ID</span>
542
+ <span class="k">if</span> <span class="n">argument_entry</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">argument_entry</span><span class="o">.</span><span class="n">id</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
543
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Failed to save argument </span><span class="si">{</span><span class="n">arg</span><span class="si">}</span><span class="s2"> - returned None or invalid ID&quot;</span><span class="p">)</span>
544
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Failed to save argument of type </span><span class="si">{</span><span class="n">arg</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
545
+
546
+ <span class="n">variable_name</span> <span class="o">=</span> <span class="n">param_names</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">param_names</span><span class="p">)</span> <span class="k">else</span> <span class="sa">f</span><span class="s2">&quot;arg_</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span>
547
+
548
+ <span class="n">input_references</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">NamedDataReference</span><span class="o">.</span><span class="n">from_variable</span><span class="p">(</span>
549
+ <span class="n">argument_entry</span><span class="p">,</span>
550
+ <span class="n">variable_name</span><span class="o">=</span><span class="n">variable_name</span><span class="p">,</span>
551
+ <span class="n">task_id</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
552
+ <span class="p">))</span>
553
+
554
+ <span class="n">delayed_message</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span> <span class="c1"># there is no task_id yet</span>
555
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
556
+ <span class="n">projects</span> <span class="o">=</span> <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">Project</span><span class="p">)</span>
557
+ <span class="k">if</span> <span class="n">projects</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="n">projects</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
558
+ <span class="n">project</span> <span class="o">=</span> <span class="n">Project</span><span class="p">(</span><span class="n">field_name</span><span class="o">=</span><span class="s2">&quot;default&quot;</span><span class="p">)</span>
559
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">project</span><span class="p">)</span>
560
+ <span class="n">project_id</span> <span class="o">=</span> <span class="n">project</span><span class="o">.</span><span class="n">id</span>
561
+ <span class="n">delayed_message</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;default project: </span><span class="si">{</span><span class="n">project_id</span><span class="si">}</span><span class="s2"> &quot;</span>
562
+ <span class="k">else</span><span class="p">:</span>
563
+ <span class="n">project</span> <span class="o">=</span> <span class="n">projects</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
564
+ <span class="n">project_id</span> <span class="o">=</span> <span class="n">project</span><span class="o">.</span><span class="n">id</span>
565
+ <span class="n">delayed_message</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;project: </span><span class="si">{</span><span class="n">project_id</span><span class="si">}</span><span class="s2"> &quot;</span>
566
+ <span class="k">else</span><span class="p">:</span>
567
+ <span class="n">parent_registry_entry</span> <span class="o">=</span> <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">load_task_by_id</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">)</span>
568
+ <span class="n">project_id</span> <span class="o">=</span> <span class="n">parent_registry_entry</span><span class="o">.</span><span class="n">project</span>
569
+ <span class="n">delayed_message</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;using parent project: </span><span class="si">{</span><span class="n">project_id</span><span class="si">}</span><span class="s2"> &quot;</span>
570
+
571
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="o">=</span> <span class="n">NodeRegistry</span><span class="p">(</span>
572
+ <span class="n">name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
573
+ <span class="n">input_references</span><span class="o">=</span><span class="n">input_references</span><span class="p">,</span>
574
+ <span class="n">is_async</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">is_async</span><span class="p">,</span>
575
+ <span class="n">status</span><span class="o">=</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">SUBMITTED</span><span class="p">,</span>
576
+ <span class="n">custom_name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">custom_name</span><span class="p">,</span>
577
+ <span class="n">function_hash</span><span class="o">=</span><span class="n">function_hash</span><span class="p">,</span>
578
+ <span class="n">arg_hash</span><span class="o">=</span><span class="n">arg_hash</span><span class="p">,</span>
579
+ <span class="n">project</span><span class="o">=</span><span class="n">project_id</span><span class="p">,</span>
580
+ <span class="n">parent_ids</span><span class="o">=</span><span class="p">[]</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">],</span>
581
+ <span class="n">parameters</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="p">,</span>
582
+ <span class="n">func_mapping</span><span class="o">=</span><span class="n">function_mapping</span><span class="o">.</span><span class="n">function_mapping</span><span class="p">,</span>
583
+ <span class="n">call_path</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">call_path</span><span class="p">,</span>
584
+ <span class="p">)</span>
585
+
586
+ <span class="k">if</span> <span class="n">delayed_message</span><span class="p">:</span>
587
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> with name </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">delayed_message</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
588
+ <span class="n">parent_parameters</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_function_kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;parent_parameters&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
589
+ <span class="n">registry_entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span>
590
+ <span class="k">assert</span> <span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
591
+ <span class="k">await</span> <span class="n">apply_resource_assignment_to_node_registry</span><span class="p">(</span>
592
+ <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="p">,</span>
593
+ <span class="n">registry_entry</span><span class="p">,</span>
594
+ <span class="n">parent_parameters</span><span class="o">=</span><span class="n">parent_parameters</span>
595
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">parent_parameters</span><span class="p">,</span> <span class="n">Parameters</span><span class="p">)</span>
596
+ <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
597
+ <span class="p">)</span>
598
+ <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span> <span class="o">=</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">parameters</span>
599
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">registry_entry</span><span class="p">)</span>
600
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
601
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> with name </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> created for resource: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span><span class="si">}</span><span class="s2"> queue: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">queue</span><span class="si">}</span><span class="s2"> with id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">&quot;</span>
602
+ <span class="p">)</span>
603
+ <span class="k">return</span> <span class="n">registry_entry</span></div>
604
+
605
+
606
+ <div class="viewcode-block" id="Node.get_node_registry">
607
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.get_node_registry">[docs]</a>
608
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_node_registry</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">TaskStatus</span><span class="p">:</span>
609
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
610
+ <span class="sd"> Reads or initializes the task registry entry in the database.</span>
611
+
612
+ <span class="sd"> This method ensures that a task entry exists in the database for the</span>
613
+ <span class="sd"> current task. It computes hashes of its arguments and function,</span>
614
+ <span class="sd"> checks if a database entry already matches these hashes, and creates</span>
615
+ <span class="sd"> a new entry if no match is found. If the database is not connected,</span>
616
+ <span class="sd"> an exception is raised.</span>
617
+
618
+ <span class="sd"> :raises ValueError: if the database is not connected.</span>
619
+ <span class="sd"> :return: Status of the task retrieved or created.</span>
620
+ <span class="sd"> :rtype: TaskStatus</span>
621
+ <span class="sd"> &quot;&quot;&quot;</span>
622
+ <span class="k">if</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
623
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Database is not connected&quot;</span><span class="p">)</span>
624
+
625
+ <span class="n">arg_hash</span> <span class="o">=</span> <span class="n">compute_arg_hash</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="p">)</span>
626
+ <span class="c1"># THE FUNCTION HASH IS NO LONGER USED</span>
627
+ <span class="n">function_hash</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span> <span class="c1"># complex_hash_function(self._func)</span>
628
+ <span class="bp">self</span><span class="o">.</span><span class="n">_arg_hash</span> <span class="o">=</span> <span class="n">arg_hash</span>
629
+ <span class="bp">self</span><span class="o">.</span><span class="n">_function_hash</span> <span class="o">=</span> <span class="n">function_hash</span>
630
+
631
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="o">=</span> <span class="p">(</span>
632
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">load_task</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">arg_hash</span><span class="p">,</span> <span class="n">function_hash</span><span class="p">)</span>
633
+ <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">force_rerun</span>
634
+ <span class="k">else</span> <span class="kc">None</span>
635
+ <span class="p">)</span>
636
+
637
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
638
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">make_registry_entry</span><span class="p">(</span><span class="n">function_hash</span><span class="p">,</span> <span class="n">arg_hash</span><span class="p">)</span>
639
+ <span class="k">else</span><span class="p">:</span>
640
+
641
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">:</span>
642
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
643
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> adding parent_id </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="si">}</span><span class="s2"> to task: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&quot;</span>
644
+ <span class="p">)</span>
645
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
646
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
647
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> parent_id is a string: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="si">}</span><span class="s2">&quot;</span>
648
+ <span class="p">)</span>
649
+ <span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span> <span class="o">=</span> <span class="n">ObjectId</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">)</span>
650
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">parent_ids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parent_id</span><span class="p">)</span>
651
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">)</span>
652
+ <span class="c1"># whenever a task is found in the database, we may have to redo all child artifacts because the children</span>
653
+ <span class="c1"># will not be loaded</span>
654
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">recompute_artifacts</span><span class="p">:</span>
655
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
656
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> recomputing artifacts for task: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&quot;</span>
657
+ <span class="p">)</span>
658
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.recompute_artifacts</span><span class="w"> </span><span class="kn">import</span> <span class="n">recompute_artifacts</span>
659
+
660
+ <span class="k">await</span> <span class="n">recompute_artifacts</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">)</span>
661
+ <span class="k">else</span><span class="p">:</span>
662
+ <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
663
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> was found in the database with status: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span><span class="si">}</span><span class="s2">. Terminating execution.&quot;</span>
664
+ <span class="p">)</span>
665
+
666
+ <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
667
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span></div>
668
+
669
+
670
+ <div class="viewcode-block" id="Node.load_results">
671
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.load_results">[docs]</a>
672
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">load_results</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="n">Model</span><span class="p">,</span> <span class="n">SimstackResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
673
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
674
+ <span class="sd"> Loads the results associated with a specific task from the database. This</span>
675
+ <span class="sd"> method verifies whether the task has valid result identifiers. If valid</span>
676
+ <span class="sd"> identifiers (results_id and results_table_name) exist, it attempts to fetch</span>
677
+ <span class="sd"> the outputs.</span>
678
+
679
+ <span class="sd"> If the task status is not TaskStatus.COMPLETED None is returned which results in a RuntimeError</span>
680
+ <span class="sd"> If the results are not found or if the retrieval process fails, a `ValueError` is raised.</span>
681
+
682
+ <span class="sd"> :raises ValueError: If the task has completed but lacks output identifiers</span>
683
+ <span class="sd"> (`results_id` or `results_table_name`), or if there is any error</span>
684
+ <span class="sd"> during the process of loading the results.</span>
685
+
686
+ <span class="sd"> :return: The retrieved task outputs from the database.</span>
687
+ <span class="sd"> &quot;&quot;&quot;</span>
688
+ <span class="n">db</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span>
689
+ <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
690
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
691
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> loading results with task status </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">status</span><span class="si">}</span><span class="s2">&quot;</span>
692
+ <span class="p">)</span>
693
+ <span class="k">try</span><span class="p">:</span>
694
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
695
+ <span class="k">return</span> <span class="kc">None</span>
696
+
697
+ <span class="n">simstack_result</span> <span class="o">=</span> <span class="n">SimstackResult</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span><span class="p">)</span>
698
+ <span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
699
+ <span class="k">for</span> <span class="n">ref</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">results_references</span><span class="p">:</span>
700
+ <span class="n">model</span> <span class="o">=</span> <span class="k">await</span> <span class="n">import_class</span><span class="p">(</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_mapping</span><span class="p">,</span> <span class="n">db</span><span class="p">)</span>
701
+ <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">find_one</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">model</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">ref</span><span class="o">.</span><span class="n">reference</span><span class="p">)</span>
702
+ <span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
703
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">)</span>
704
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
705
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> could not find result with id </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">reference</span><span class="si">}</span><span class="s2"> in table </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_mapping</span><span class="si">}</span><span class="s2">&quot;</span>
706
+ <span class="p">)</span>
707
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
708
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> could not find result with id </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">reference</span><span class="si">}</span><span class="s2"> in table </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_mapping</span><span class="si">}</span><span class="s2">&quot;</span>
709
+ <span class="p">)</span>
710
+ <span class="n">simstack_result</span><span class="o">.</span><span class="fm">__setattr__</span><span class="p">(</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_name</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
711
+
712
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> loaded outputs&quot;</span><span class="p">)</span>
713
+
714
+ <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">results_references</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
715
+ <span class="k">return</span> <span class="n">result</span> <span class="c1"># there is only one result, return it directly</span>
716
+ <span class="k">else</span><span class="p">:</span>
717
+ <span class="k">return</span> <span class="n">simstack_result</span> <span class="c1"># return the SimstackResult with all results</span>
718
+
719
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
720
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">)</span>
721
+ <span class="n">logger</span><span class="o">.</span><span class="n">exception</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed to load outputs: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
722
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed to load outputs: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span></div>
723
+
724
+
725
+ <div class="viewcode-block" id="Node.run_somewhere">
726
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.run_somewhere">[docs]</a>
727
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">run_somewhere</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="n">Model</span><span class="p">,</span> <span class="n">SimstackResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
728
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
729
+ <span class="sd"> Executes the task either locally or on a remote resource. This function ensures that</span>
730
+ <span class="sd"> if the task is meant to execute on a remote resource, it waits for the task to complete</span>
731
+ <span class="sd"> remotely and fetches its results. If the task executes locally, it directly runs the task</span>
732
+ <span class="sd"> and retrieves the results.</span>
733
+
734
+ <span class="sd"> If any exception occurs during the execution, the status is updated to `FAILED`</span>
735
+ <span class="sd"> and the exception is logged.</span>
736
+
737
+ <span class="sd"> :return: A single Model or a list of Model instances of the task results or None. If the task</span>
738
+ <span class="sd"> is not completed successfully.</span>
739
+ <span class="sd"> :rtype: Model | SimstackResult</span>
740
+
741
+ <span class="sd"> :raises RunTimeError: When task execution fails due to an unexpected exception.</span>
742
+ <span class="sd"> &quot;&quot;&quot;</span>
743
+ <span class="n">resource_self</span> <span class="o">=</span> <span class="n">Resource</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="s2">&quot;self&quot;</span><span class="p">)</span>
744
+
745
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
746
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> run_somewhere context resource: </span><span class="si">{</span><span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">resource</span><span class="si">}</span><span class="s2"> target resource: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span><span class="si">}</span><span class="s2"> queue: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">queue</span><span class="si">}</span><span class="s2">&quot;</span>
747
+ <span class="p">)</span>
748
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span> <span class="o">==</span> <span class="n">resource_self</span> <span class="ow">or</span> <span class="p">(</span>
749
+ <span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">resource</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span>
750
+ <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">queue</span> <span class="o">==</span> <span class="n">Queue</span><span class="o">.</span><span class="n">DEFAULT</span>
751
+ <span class="p">):</span>
752
+ <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">execute_node_locally</span><span class="p">()</span>
753
+ <span class="k">return</span> <span class="n">result</span>
754
+ <span class="k">else</span><span class="p">:</span>
755
+ <span class="k">if</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">_submit_slurm_child_from_current_resource</span><span class="p">():</span>
756
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
757
+ <span class="s2">&quot;Task task_id: </span><span class="si">%s</span><span class="s2"> submitted nested Slurm child directly from resource </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span>
758
+ <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">,</span>
759
+ <span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">resource</span><span class="p">,</span>
760
+ <span class="p">)</span>
761
+ <span class="c1"># the task will be executed somewhere else</span>
762
+ <span class="c1"># wait for the database status to change</span>
763
+ <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
764
+ <span class="n">new_registry_entry</span> <span class="o">=</span> <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">load_task_by_id</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
765
+ <span class="c1"># TODO add timeout mechanism here</span>
766
+ <span class="k">if</span> <span class="n">new_registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
767
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
768
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> could not be found in the database&quot;</span>
769
+ <span class="p">)</span>
770
+ <span class="n">new_status</span> <span class="o">=</span> <span class="n">new_registry_entry</span><span class="o">.</span><span class="n">status</span>
771
+ <span class="k">if</span> <span class="p">(</span>
772
+ <span class="n">new_status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">RUNNING</span>
773
+ <span class="ow">and</span> <span class="n">new_status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SUBMITTED</span>
774
+ <span class="ow">and</span> <span class="n">new_status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SLURM_QUEUED</span>
775
+ <span class="ow">and</span> <span class="n">new_status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">RETRIEVED</span>
776
+ <span class="p">):</span>
777
+ <span class="k">break</span>
778
+
779
+ <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> is waiting for results&quot;</span><span class="p">)</span>
780
+ <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
781
+
782
+ <span class="k">if</span> <span class="n">new_status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
783
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> completed remotely&quot;</span><span class="p">)</span>
784
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="o">=</span> <span class="n">new_registry_entry</span>
785
+ <span class="k">return</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">load_results</span><span class="p">()</span>
786
+ <span class="k">else</span><span class="p">:</span>
787
+ <span class="k">return</span> <span class="kc">None</span></div>
788
+
789
+
790
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">_submit_slurm_child_from_current_resource</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
791
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
792
+ <span class="k">return</span> <span class="kc">False</span>
793
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">queue</span> <span class="o">!=</span> <span class="n">Queue</span><span class="o">.</span><span class="n">SLURM_QUEUE</span><span class="p">:</span>
794
+ <span class="k">return</span> <span class="kc">False</span>
795
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span> <span class="o">!=</span> <span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">resource</span><span class="p">:</span>
796
+ <span class="k">return</span> <span class="kc">False</span>
797
+ <span class="k">if</span> <span class="ow">not</span> <span class="k">await</span> <span class="n">claim_submitted_node</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">):</span>
798
+ <span class="k">return</span> <span class="kc">False</span>
799
+
800
+ <span class="kn">from</span><span class="w"> </span><span class="nn">simstack.core.submit_node</span><span class="w"> </span><span class="kn">import</span> <span class="n">submit_node</span>
801
+
802
+ <span class="k">await</span> <span class="n">submit_node</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">)</span>
803
+ <span class="k">return</span> <span class="kc">True</span>
804
+
805
+ <div class="viewcode-block" id="Node.execute_node_locally">
806
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.execute_node_locally">[docs]</a>
807
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">execute_node_locally</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="n">Model</span><span class="p">,</span> <span class="n">SimstackResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
808
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
809
+ <span class="sd"> Executes a specified node in the current context locally, either asynchronously or</span>
810
+ <span class="sd"> synchronously, managing task status updates, directory changes, and result persistence.</span>
811
+
812
+ <span class="sd"> This method handles the execution of a computational task represented as a &quot;node&quot;. It</span>
813
+ <span class="sd"> manages the task&#39;s status transitions, file system operations for managing working</span>
814
+ <span class="sd"> directories, and handling output results, including their persistence in a database.</span>
815
+ <span class="sd"> The method supports both asynchronous and synchronous node execution. It verifies</span>
816
+ <span class="sd"> results, handles exceptions, and manages task metadata updates.</span>
817
+
818
+ <span class="sd"> Nodes can either return</span>
819
+ <span class="sd"> * a single `Model` instance</span>
820
+ <span class="sd"> * a `SimstackResult` instance</span>
821
+ <span class="sd"> * None (for failure).</span>
822
+ <span class="sd"> * a boolean value (for failure or success if there are no results)</span>
823
+
824
+ <span class="sd"> There is a try-except block around the actual execution of the node which generates a log entry</span>
825
+ <span class="sd"> &quot;node function error for node&quot; that catches all uncaught exceptions within the node. These error are</span>
826
+ <span class="sd"> not propagated, but the task status is set to TaskStatus.FAILED.</span>
827
+
828
+ <span class="sd"> :param self: Instance of the class invoking this method.</span>
829
+
830
+ <span class="sd"> :raises Exception: for failures of the Simstack logic</span>
831
+
832
+ <span class="sd"> :return: The processed result of the node execution. Depending on the task&#39;s output,</span>
833
+ <span class="sd"> it could be of the type `Model`, `SimstackResult`, or be None if no valid result</span>
834
+ <span class="sd"> was produced.</span>
835
+
836
+ <span class="sd"> &quot;&quot;&quot;</span>
837
+ <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
838
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">started_at</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
839
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">RUNNING</span><span class="p">)</span>
840
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
841
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> is started on </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span><span class="si">}</span><span class="s2"> in Node:execute_node_locally&quot;</span>
842
+ <span class="p">)</span>
843
+ <span class="n">original_dir</span> <span class="o">=</span> <span class="n">Path</span><span class="o">.</span><span class="n">cwd</span><span class="p">()</span>
844
+ <span class="k">try</span><span class="p">:</span>
845
+ <span class="n">node_runner</span> <span class="o">=</span> <span class="n">NodeRunner</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_func</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
846
+ <span class="n">node_kwargs</span> <span class="o">=</span> <span class="p">{</span>
847
+ <span class="s2">&quot;node_runner&quot;</span><span class="p">:</span> <span class="n">node_runner</span><span class="p">,</span>
848
+ <span class="s2">&quot;parent_id&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">,</span>
849
+ <span class="s2">&quot;task_id&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">,</span>
850
+ <span class="s2">&quot;call_path&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">call_path</span><span class="p">,</span>
851
+ <span class="s2">&quot;parent_parameters&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="p">,</span> <span class="c1"># this must have a name different from parameters, because</span>
852
+ <span class="c1"># otherwise this setting will override all the parameters of</span>
853
+ <span class="c1"># the child nodes</span>
854
+ <span class="s2">&quot;recompute_artifacts&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">recompute_artifacts</span><span class="p">,</span>
855
+ <span class="s2">&quot;custom_name&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">custom_name</span><span class="p">,</span>
856
+ <span class="s2">&quot;arg_hash&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_arg_hash</span><span class="p">,</span>
857
+ <span class="s2">&quot;function_hash&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_function_hash</span><span class="p">,</span>
858
+ <span class="p">}</span>
859
+
860
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">force_rerun</span><span class="p">:</span>
861
+ <span class="n">node_kwargs</span><span class="p">[</span><span class="s2">&quot;force_rerun&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
862
+
863
+ <span class="n">path</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">workdir</span><span class="p">)</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">/</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
864
+ <span class="c1"># Create the directory if it doesn&#39;t exist</span>
865
+ <span class="n">path</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">parents</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
866
+ <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
867
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
868
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> successfully changed to directory: </span><span class="si">{</span><span class="n">path</span><span class="o">.</span><span class="n">absolute</span><span class="p">()</span><span class="si">}</span><span class="s2">&quot;</span>
869
+ <span class="p">)</span>
870
+
871
+ <span class="c1"># real_func_wrapper = await import_function_by_name(self._func.__name__,self.id)</span>
872
+ <span class="c1"># real_func = getattr(real_func_wrapper, &#39;_inner&#39;, real_func_wrapper)</span>
873
+ <span class="n">real_func</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_func</span>
874
+ <span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
875
+ <span class="n">set_task_id</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
876
+ <span class="k">try</span><span class="p">:</span>
877
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_async</span><span class="p">:</span>
878
+ <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">real_func</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="p">,</span> <span class="o">**</span><span class="n">node_kwargs</span><span class="p">)</span>
879
+ <span class="k">else</span><span class="p">:</span>
880
+ <span class="n">result</span> <span class="o">=</span> <span class="n">real_func</span><span class="p">(</span><span class="o">*</span><span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="p">,</span> <span class="o">**</span><span class="n">node_kwargs</span><span class="p">)</span>
881
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
882
+ <span class="c1"># Save the error message if possible</span>
883
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">:</span>
884
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">error</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
885
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">)</span>
886
+ <span class="n">logger</span><span class="o">.</span><span class="n">exception</span><span class="p">(</span>
887
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> node function error for node: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> msg: </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
888
+ <span class="p">)</span>
889
+ <span class="c1"># save what we can, in particular the info_files</span>
890
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">process_results</span><span class="p">(</span><span class="n">node_runner</span><span class="p">)</span>
891
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">)</span>
892
+ <span class="k">raise</span>
893
+ <span class="k">finally</span><span class="p">:</span>
894
+ <span class="n">clear_task_id</span><span class="p">()</span>
895
+
896
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">completed_at</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
897
+
898
+ <span class="n">new_task_status</span><span class="p">,</span> <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">process_results</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
899
+
900
+ <span class="k">if</span> <span class="n">new_task_status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
901
+ <span class="n">artifact_arguments</span> <span class="o">=</span> <span class="n">ArtifactArguments</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
902
+ <span class="n">artifact_arguments</span><span class="o">.</span><span class="n">add_attributes</span><span class="p">(</span>
903
+ <span class="bp">self</span><span class="o">.</span><span class="n">_func</span><span class="p">,</span> <span class="o">*</span><span class="bp">self</span><span class="o">.</span><span class="n">_args</span><span class="p">,</span> <span class="o">**</span><span class="n">node_kwargs</span>
904
+ <span class="p">)</span>
905
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">artifact_ids</span> <span class="o">=</span> <span class="k">await</span> <span class="n">create_artifacts</span><span class="p">(</span>
906
+ <span class="n">artifact_arguments</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span>
907
+ <span class="p">)</span>
908
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span>
909
+ <span class="n">new_task_status</span>
910
+ <span class="p">)</span> <span class="c1"># this will also commit the registry entry</span>
911
+
912
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
913
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> is finished on resource: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parameters</span><span class="o">.</span><span class="n">resource</span><span class="si">}</span><span class="s2"> with task status: </span><span class="si">{</span><span class="n">new_task_status</span><span class="si">}</span><span class="s2">&quot;</span>
914
+ <span class="p">)</span>
915
+ <span class="k">if</span> <span class="n">new_task_status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
916
+ <span class="k">return</span> <span class="kc">None</span>
917
+ <span class="k">return</span> <span class="n">result</span>
918
+ <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
919
+ <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">set_status</span><span class="p">(</span><span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">)</span>
920
+ <span class="k">raise</span>
921
+ <span class="k">finally</span><span class="p">:</span>
922
+ <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">original_dir</span><span class="p">)</span>
923
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
924
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> successfully back to directory: </span><span class="si">{</span><span class="n">original_dir</span><span class="o">.</span><span class="n">absolute</span><span class="p">()</span><span class="si">}</span><span class="s2">&quot;</span>
925
+ <span class="p">)</span></div>
926
+
927
+
928
+ <div class="viewcode-block" id="Node.process_results">
929
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.process_results">[docs]</a>
930
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">process_results</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">[</span><span class="n">TaskStatus</span><span class="p">,</span> <span class="n">Any</span><span class="p">]:</span>
931
+ <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
932
+ <span class="c1"># each of the following if sets the result either to a valid value or None</span>
933
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span>
934
+ <span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
935
+ <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> returned None&quot;</span><span class="p">)</span>
936
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span> <span class="c1"># result is None</span>
937
+ <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
938
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
939
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span>
940
+ <span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
941
+ <span class="k">elif</span> <span class="n">is_simstack_model</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">SimstackResult</span><span class="p">):</span>
942
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">SimstackResult</span><span class="p">):</span>
943
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">status</span>
944
+ <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s2">&quot;custom_name&quot;</span><span class="p">):</span>
945
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">custom_name</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">custom_name</span>
946
+
947
+ <span class="k">for</span> <span class="n">file_stack</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">info_files</span><span class="p">:</span>
948
+ <span class="k">if</span> <span class="n">file_stack</span><span class="p">:</span>
949
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">file_stack</span><span class="p">,</span> <span class="n">FileStack</span><span class="p">):</span>
950
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
951
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> saving info file: </span><span class="si">{</span><span class="n">file_stack</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">file_stack</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">&quot;</span>
952
+ <span class="p">)</span>
953
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">info_files</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
954
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">info_files</span> <span class="o">=</span> <span class="n">FileList</span><span class="p">()</span>
955
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">file_stack</span><span class="p">)</span>
956
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">info_files</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">file_stack</span><span class="p">)</span>
957
+ <span class="k">else</span><span class="p">:</span>
958
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
959
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> cannot save info_file: FileStack expected but got </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">file_stack</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
960
+ <span class="p">)</span>
961
+ <span class="k">else</span><span class="p">:</span>
962
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> saving info-file is NONE&quot;</span><span class="p">)</span>
963
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;saving info file is NONE&quot;</span><span class="p">)</span>
964
+
965
+ <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">error_message</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">result</span><span class="o">.</span><span class="n">error_message</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
966
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
967
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> returned with error: </span><span class="si">{</span><span class="n">result</span><span class="o">.</span><span class="n">error_message</span><span class="si">}</span><span class="s2">&quot;</span>
968
+ <span class="p">)</span>
969
+ <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">message</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">result</span><span class="o">.</span><span class="n">message</span> <span class="o">!=</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
970
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> message: </span><span class="si">{</span><span class="n">result</span><span class="o">.</span><span class="n">message</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
971
+ <span class="k">else</span><span class="p">:</span>
972
+ <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s2">&quot;status&quot;</span><span class="p">):</span>
973
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">status</span>
974
+ <span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s2">&quot;task_status&quot;</span><span class="p">):</span>
975
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">task_status</span>
976
+
977
+ <span class="n">results_references</span><span class="p">,</span> <span class="n">result_models</span> <span class="o">=</span> <span class="k">await</span> <span class="n">process_result_helper</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="p">))</span>
978
+
979
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">results_references</span> <span class="o">=</span> <span class="n">results_references</span>
980
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">new_task_status</span>
981
+
982
+ <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">results_references</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
983
+ <span class="n">result</span> <span class="o">=</span> <span class="n">result_models</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># for a SimstackResult with just one returned model we return the model directly</span>
984
+ <span class="k">else</span><span class="p">:</span>
985
+ <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
986
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> returned a result of type </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="si">}</span><span class="s2"> which is not a SimstackModel or a SimstackResult&quot;</span>
987
+ <span class="p">)</span>
988
+ <span class="n">new_task_status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span>
989
+ <span class="k">return</span> <span class="n">new_task_status</span><span class="p">,</span> <span class="n">result</span></div>
990
+
991
+
992
+ <div class="viewcode-block" id="Node.set_status">
993
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.Node.set_status">[docs]</a>
994
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">set_status</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">status</span><span class="p">:</span> <span class="n">TaskStatus</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
995
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
996
+ <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Task has no registry entry&quot;</span><span class="p">)</span>
997
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">TaskStatus</span><span class="p">):</span>
998
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">status</span>
999
+ <span class="k">else</span><span class="p">:</span>
1000
+ <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">status</span><span class="si">}</span><span class="s2"> is not a TaskStatus&quot;</span><span class="p">)</span>
1001
+ <span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="p">(</span><span class="n">status</span><span class="p">)</span>
1002
+ <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">registry_entry</span><span class="p">)</span>
1003
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> is set to </span><span class="si">{</span><span class="n">status</span><span class="si">}</span><span class="s2">, id is: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span></div>
1004
+ </div>
1005
+
1006
+
1007
+
1008
+ <div class="viewcode-block" id="node_from_database">
1009
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.node_from_database">[docs]</a>
1010
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">node_from_database</span><span class="p">(</span><span class="n">registry_entry</span><span class="p">:</span> <span class="n">NodeRegistry</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="s2">&quot;Node&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
1011
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
1012
+ <span class="sd"> Constructs an instance of the class from database information encoded in a</span>
1013
+ <span class="sd"> registry entry.</span>
1014
+
1015
+ <span class="sd"> This method retrieves input arguments and the serialized function from the</span>
1016
+ <span class="sd"> database using information provided in the `registry_entry`. It then deserializes</span>
1017
+ <span class="sd"> the function and initializes a corresponding Node instance, associating it</span>
1018
+ <span class="sd"> with the given registry entry.</span>
1019
+
1020
+ <span class="sd"> This function can delete the registry_entry !!!</span>
1021
+ <span class="sd"> The only way that registry_entry.function_hash is &quot;NOT INITIALIZED&quot; is when the node</span>
1022
+ <span class="sd"> is created from the frontend. No other node is listening specifically for this registry_entry to complete.</span>
1023
+ <span class="sd"> If a duplicate is found the node from the duplication is returned</span>
1024
+
1025
+ <span class="sd"> :param registry_entry: The registry entry containing information necessary to</span>
1026
+ <span class="sd"> reconstruct the Node instance. Includes input table names, function pickled</span>
1027
+ <span class="sd"> as a string, and other metadata.</span>
1028
+ <span class="sd"> :type registry_entry: NodeRegistry</span>
1029
+
1030
+ <span class="sd"> :return: A reconstructed Node instance based on the registry entry, or None if</span>
1031
+ <span class="sd"> the deserialized function is not valid or there was an error.</span>
1032
+ <span class="sd"> :rtype: Optional[Node]</span>
1033
+ <span class="sd"> &quot;&quot;&quot;</span>
1034
+ <span class="n">args</span> <span class="o">=</span> <span class="p">[]</span>
1035
+ <span class="n">db</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span>
1036
+
1037
+ <span class="k">for</span> <span class="n">ref</span> <span class="ow">in</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">input_references</span><span class="p">:</span>
1038
+ <span class="k">try</span><span class="p">:</span>
1039
+ <span class="n">model</span> <span class="o">=</span> <span class="k">await</span> <span class="n">import_class</span><span class="p">(</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_mapping</span><span class="p">,</span> <span class="n">db</span><span class="p">)</span>
1040
+ <span class="n">arg</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">find_one</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">model</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">ref</span><span class="o">.</span><span class="n">reference</span><span class="p">)</span>
1041
+ <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
1042
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1043
+ <span class="n">logger</span><span class="o">.</span><span class="n">exception</span><span class="p">(</span>
1044
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed to load input </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">variable_mapping</span><span class="si">}</span><span class="s2"> with id </span><span class="si">{</span><span class="n">ref</span><span class="o">.</span><span class="n">reference</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
1045
+ <span class="p">)</span>
1046
+ <span class="k">return</span> <span class="kc">None</span>
1047
+
1048
+ <span class="k">if</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">arg_hash</span> <span class="o">==</span> <span class="s2">&quot;NOT INITIALIZED&quot;</span><span class="p">:</span>
1049
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> computes arg hashes&quot;</span><span class="p">)</span>
1050
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">arg_hash</span> <span class="o">=</span> <span class="n">compute_arg_hash</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
1051
+
1052
+
1053
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
1054
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> loaded </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span><span class="si">}</span><span class="s2"> inputs in Node:node_from_database status: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span><span class="si">}</span><span class="s2">&quot;</span>
1055
+ <span class="p">)</span>
1056
+ <span class="n">func</span> <span class="o">=</span> <span class="kc">None</span>
1057
+ <span class="k">try</span><span class="p">:</span>
1058
+ <span class="n">wrapped_func</span> <span class="o">=</span> <span class="k">await</span> <span class="n">import_function</span><span class="p">(</span>
1059
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">func_mapping</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">task_id</span><span class="o">=</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span>
1060
+ <span class="p">)</span>
1061
+ <span class="k">if</span> <span class="n">wrapped_func</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
1062
+ <span class="c1"># for nodes the mapping points to the wrapped func to we use that</span>
1063
+ <span class="n">func</span> <span class="o">=</span> <span class="p">(</span>
1064
+ <span class="n">wrapped_func</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">wrapped_func</span><span class="p">,</span> <span class="s2">&quot;_inner&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="n">wrapped_func</span><span class="o">.</span><span class="n">_inner</span>
1065
+ <span class="p">)</span>
1066
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
1067
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> inner: </span><span class="si">{</span><span class="nb">hasattr</span><span class="p">(</span><span class="n">wrapped_func</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;_inner&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2"> imported function: </span><span class="si">{</span><span class="n">func</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">&quot;</span>
1068
+ <span class="p">)</span>
1069
+ <span class="k">if</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">function_hash</span> <span class="o">==</span> <span class="s2">&quot;NOT INITIALIZED&quot;</span><span class="p">:</span>
1070
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">function_hash</span> <span class="o">=</span> <span class="n">cast</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">complex_hash_function</span><span class="p">(</span><span class="n">func</span><span class="p">))</span>
1071
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">is_async</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">iscoroutinefunction</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
1072
+ <span class="k">else</span><span class="p">:</span>
1073
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
1074
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> could not import function </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">func_mapping</span><span class="si">}</span><span class="s2">&quot;</span>
1075
+ <span class="p">)</span>
1076
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1077
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
1078
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed to import function </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">func_mapping</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
1079
+ <span class="p">)</span>
1080
+
1081
+ <span class="k">if</span> <span class="n">func</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">function_hash</span> <span class="o">==</span> <span class="s2">&quot;NOT INITIALIZED&quot;</span><span class="p">:</span>
1082
+ <span class="k">return</span> <span class="kc">None</span>
1083
+
1084
+ <span class="k">try</span><span class="p">:</span>
1085
+ <span class="n">duplicate_entry</span> <span class="o">=</span> <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">find_one</span><span class="p">(</span>
1086
+ <span class="n">NodeRegistry</span><span class="p">,</span>
1087
+ <span class="p">(</span><span class="n">NodeRegistry</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
1088
+ <span class="o">&amp;</span> <span class="p">(</span><span class="n">NodeRegistry</span><span class="o">.</span><span class="n">arg_hash</span> <span class="o">==</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">arg_hash</span><span class="p">)</span>
1089
+ <span class="o">&amp;</span> <span class="p">(</span><span class="n">NodeRegistry</span><span class="o">.</span><span class="n">function_hash</span> <span class="o">==</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">function_hash</span><span class="p">)</span>
1090
+ <span class="o">&amp;</span> <span class="p">(</span><span class="n">NodeRegistry</span><span class="o">.</span><span class="n">id</span> <span class="o">!=</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="p">),</span>
1091
+ <span class="p">)</span>
1092
+ <span class="k">if</span> <span class="n">duplicate_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1093
+ <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">save</span><span class="p">(</span>
1094
+ <span class="n">registry_entry</span>
1095
+ <span class="p">)</span> <span class="c1"># save the fixed entry AFTER checking for duplicates</span>
1096
+ <span class="c1"># the calling function may have the originial entry unsaved !</span>
1097
+ <span class="k">else</span><span class="p">:</span>
1098
+ <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
1099
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> found duplicate entry </span><span class="si">{</span><span class="n">duplicate_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">duplicate_entry</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">&quot;</span>
1100
+ <span class="p">)</span>
1101
+
1102
+ <span class="c1"># the parameters of the new job may be different</span>
1103
+ <span class="n">duplicate_entry</span><span class="o">.</span><span class="n">parameters</span> <span class="o">=</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">parameters</span>
1104
+ <span class="k">await</span> <span class="n">db</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="n">registry_entry</span><span class="p">)</span>
1105
+ <span class="n">registry_entry</span> <span class="o">=</span> <span class="n">duplicate_entry</span>
1106
+
1107
+ <span class="k">if</span> <span class="n">func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1108
+ <span class="c1"># we recovered a duplicate, let&#39;s try to import the function from the duplicate&#39;s mapping</span>
1109
+ <span class="k">try</span><span class="p">:</span>
1110
+ <span class="n">wrapped_func</span> <span class="o">=</span> <span class="k">await</span> <span class="n">import_function</span><span class="p">(</span>
1111
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">func_mapping</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">task_id</span><span class="o">=</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span>
1112
+ <span class="p">)</span>
1113
+ <span class="k">if</span> <span class="n">wrapped_func</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
1114
+ <span class="n">func</span> <span class="o">=</span> <span class="p">(</span>
1115
+ <span class="n">wrapped_func</span>
1116
+ <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">wrapped_func</span><span class="p">,</span> <span class="s2">&quot;_inner&quot;</span><span class="p">)</span>
1117
+ <span class="k">else</span> <span class="n">wrapped_func</span><span class="o">.</span><span class="n">_inner</span>
1118
+ <span class="p">)</span>
1119
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1120
+ <span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
1121
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed to import function from duplicate </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">func_mapping</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
1122
+ <span class="p">)</span>
1123
+
1124
+ <span class="k">if</span> <span class="n">func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1125
+ <span class="k">return</span> <span class="kc">None</span>
1126
+
1127
+ <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
1128
+ <span class="n">logger</span><span class="o">.</span><span class="n">exception</span><span class="p">(</span>
1129
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> failed during duplicate detection or secondary import </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span>
1130
+ <span class="p">)</span>
1131
+ <span class="k">return</span> <span class="kc">None</span>
1132
+
1133
+ <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{</span>
1134
+ <span class="s2">&quot;func&quot;</span><span class="p">:</span> <span class="n">func</span><span class="p">,</span>
1135
+ <span class="s2">&quot;is_async&quot;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>
1136
+ <span class="s2">&quot;call_path&quot;</span><span class="p">:</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">call_path</span><span class="p">,</span>
1137
+ <span class="s2">&quot;parameters&quot;</span><span class="p">:</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">parameters</span><span class="p">,</span>
1138
+ <span class="s2">&quot;custom_name&quot;</span><span class="p">:</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">custom_name</span><span class="p">,</span>
1139
+ <span class="s2">&quot;arg_hash&quot;</span><span class="p">:</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">arg_hash</span><span class="p">,</span>
1140
+ <span class="s2">&quot;function_hash&quot;</span><span class="p">:</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">function_hash</span><span class="p">,</span>
1141
+ <span class="p">}</span>
1142
+ <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">registry_entry</span><span class="p">,</span> <span class="s2">&quot;is_async&quot;</span><span class="p">):</span>
1143
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;is_async&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">is_async</span>
1144
+
1145
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;parent_id&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span>
1146
+ <span class="n">registry_entry</span><span class="o">.</span><span class="n">parent_ids</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">registry_entry</span><span class="o">.</span><span class="n">parent_ids</span> <span class="k">else</span> <span class="kc">None</span>
1147
+ <span class="p">)</span>
1148
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span>
1149
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> is_async: </span><span class="si">{</span><span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;is_async&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> parent_id: </span><span class="si">{</span><span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;parent_id&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span>
1150
+ <span class="p">)</span>
1151
+
1152
+ <span class="n">new_node</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
1153
+ <span class="n">new_node</span><span class="o">.</span><span class="n">registry_entry</span> <span class="o">=</span> <span class="n">registry_entry</span>
1154
+ <span class="k">return</span> <span class="n">new_node</span></div>
1155
+
1156
+
1157
+
1158
+ <span class="c1"># Add a return type annotation for async functions</span>
1159
+ <span class="c1"># T_co = TypeVar(&quot;T_co&quot;, covariant=True)</span>
1160
+ <span class="c1">#</span>
1161
+ <span class="c1"># # Create overloaded function type annotations</span>
1162
+ <span class="c1"># @overload</span>
1163
+ <span class="c1"># def node(</span>
1164
+ <span class="c1"># _func: Callable[..., Awaitable[T_co]],</span>
1165
+ <span class="c1"># ) -&gt; Callable[..., Awaitable[T_co]]: ...</span>
1166
+ <span class="c1">#</span>
1167
+ <span class="c1"># @overload</span>
1168
+ <span class="c1"># def node(</span>
1169
+ <span class="c1"># _func: Callable[..., T_co],</span>
1170
+ <span class="c1"># ) -&gt; Callable[..., T_co]: ...</span>
1171
+ <span class="c1">#</span>
1172
+ <span class="c1"># @overload</span>
1173
+ <span class="c1"># def node(</span>
1174
+ <span class="c1"># _func: None = None,</span>
1175
+ <span class="c1"># *,</span>
1176
+ <span class="c1"># name: Optional[str] = None,</span>
1177
+ <span class="c1"># version: Optional[str] = None,</span>
1178
+ <span class="c1"># cache: bool = True,</span>
1179
+ <span class="c1"># **kwargs_node,</span>
1180
+ <span class="c1"># ) -&gt; Callable[[Callable[..., Any]], Callable[..., Any]]: ...</span>
1181
+
1182
+
1183
+ <span class="n">P</span> <span class="o">=</span> <span class="n">ParamSpec</span><span class="p">(</span><span class="s2">&quot;P&quot;</span><span class="p">)</span>
1184
+
1185
+
1186
+ <span class="nd">@overload</span>
1187
+ <span class="k">def</span><span class="w"> </span><span class="nf">node</span><span class="p">(</span><span class="n">_func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">]:</span>
1188
+ <span class="o">...</span>
1189
+
1190
+
1191
+ <span class="nd">@overload</span>
1192
+ <span class="k">def</span><span class="w"> </span><span class="nf">node</span><span class="p">(</span>
1193
+ <span class="n">_func</span><span class="p">:</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1194
+ <span class="o">*</span><span class="p">,</span>
1195
+ <span class="n">name</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1196
+ <span class="n">version</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1197
+ <span class="n">cache</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
1198
+ <span class="o">**</span><span class="n">kwargs_node</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span>
1199
+ <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">Callable</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">T</span><span class="p">]],</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">]]:</span>
1200
+ <span class="o">...</span>
1201
+
1202
+
1203
+ <div class="viewcode-block" id="node">
1204
+ <a class="viewcode-back" href="../../../simstack/modules/simstack.core.html#simstack.core.node.node">[docs]</a>
1205
+ <span class="k">def</span><span class="w"> </span><span class="nf">node</span><span class="p">(</span>
1206
+ <span class="n">_func</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Callable</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">T</span><span class="p">]]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1207
+ <span class="o">*</span><span class="p">,</span>
1208
+ <span class="n">version</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
1209
+ <span class="o">**</span><span class="n">kwargs_node</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span>
1210
+ <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">],</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">Callable</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">T</span><span class="p">]],</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">]]]:</span>
1211
+ <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
1212
+ <span class="sd"> Decorator to mark a function as a node in the computation graph.</span>
1213
+ <span class="sd"> Supports both synchronous and asynchronous functions.</span>
1214
+ <span class="sd"> Can be used with or without parameters:</span>
1215
+ <span class="sd"> @node</span>
1216
+ <span class="sd"> def func(): ...</span>
1217
+
1218
+ <span class="sd"> @node(name=&quot;example&quot;)</span>
1219
+ <span class="sd"> def func(): ...</span>
1220
+
1221
+ <span class="sd"> &quot;&quot;&quot;</span>
1222
+
1223
+ <span class="k">def</span><span class="w"> </span><span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="n">P</span><span class="p">,</span> <span class="n">T</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">]:</span>
1224
+ <span class="n">is_async</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">iscoroutinefunction</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
1225
+
1226
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s2">&quot;_is_node&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
1227
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s2">&quot;_inner&quot;</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span>
1228
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s2">&quot;_node_parameters&quot;</span><span class="p">,</span> <span class="n">_parameters_from_node_kwargs</span><span class="p">(</span><span class="n">kwargs_node</span><span class="p">))</span>
1229
+
1230
+ <span class="k">def</span><span class="w"> </span><span class="nf">update_kwargs</span><span class="p">(</span><span class="n">kwargs</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Any</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
1231
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;func&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">func</span>
1232
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;is_async&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">is_async</span>
1233
+ <span class="n">explicit_parameters</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;parameters&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
1234
+ <span class="k">if</span> <span class="n">explicit_parameters</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1235
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;parameters&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="s2">&quot;_node_parameters&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">model_copy</span><span class="p">(</span>
1236
+ <span class="n">deep</span><span class="o">=</span><span class="kc">True</span>
1237
+ <span class="p">)</span>
1238
+ <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">explicit_parameters</span><span class="p">,</span> <span class="n">Parameters</span><span class="p">):</span>
1239
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;parameters&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">explicit_parameters</span><span class="o">.</span><span class="n">model_copy</span><span class="p">(</span><span class="n">deep</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
1240
+ <span class="k">else</span><span class="p">:</span>
1241
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;parameters&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">Parameters</span><span class="o">.</span><span class="n">model_validate</span><span class="p">(</span>
1242
+ <span class="n">explicit_parameters</span>
1243
+ <span class="p">)</span><span class="o">.</span><span class="n">model_copy</span><span class="p">(</span><span class="n">deep</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
1244
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;custom_name&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span>
1245
+ <span class="s2">&quot;custom_name&quot;</span><span class="p">,</span> <span class="n">kwargs_node</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;custom_name&quot;</span><span class="p">,</span> <span class="n">default_name_generator</span><span class="p">())</span>
1246
+ <span class="p">)</span>
1247
+ <span class="n">call_path</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;call_path&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span>
1248
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">call_path</span><span class="p">:</span>
1249
+ <span class="n">call_path</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
1250
+ <span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Task call_path: </span><span class="si">{</span><span class="n">call_path</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">func</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
1251
+ <span class="c1"># Fix call path construction - handle empty call_path for root nodes</span>
1252
+ <span class="k">if</span> <span class="n">call_path</span> <span class="o">==</span> <span class="s2">&quot;&quot;</span><span class="p">:</span>
1253
+ <span class="n">call_path</span> <span class="o">=</span> <span class="s2">&quot;.&quot;</span> <span class="o">+</span> <span class="n">func</span><span class="o">.</span><span class="vm">__name__</span>
1254
+ <span class="k">else</span><span class="p">:</span>
1255
+ <span class="n">call_path</span> <span class="o">=</span> <span class="n">call_path</span> <span class="o">+</span> <span class="s2">&quot;.&quot;</span> <span class="o">+</span> <span class="n">func</span><span class="o">.</span><span class="vm">__name__</span>
1256
+ <span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;call_path&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">call_path</span>
1257
+
1258
+ <span class="nd">@functools</span><span class="o">.</span><span class="n">wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
1259
+ <span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">async_wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
1260
+ <span class="n">update_kwargs</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
1261
+ <span class="c1"># Create Node with the remaining kwargs</span>
1262
+ <span class="n">execution_node</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
1263
+
1264
+ <span class="n">status</span> <span class="o">=</span> <span class="k">await</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">get_node_registry</span><span class="p">()</span>
1265
+ <span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
1266
+ <span class="k">if</span> <span class="n">status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
1267
+ <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">load_results</span><span class="p">()</span>
1268
+ <span class="c1"># TODO why do we run somewhere when already running ?</span>
1269
+ <span class="k">elif</span> <span class="n">status</span> <span class="ow">in</span> <span class="p">[</span>
1270
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SUBMITTED</span><span class="p">,</span>
1271
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">RETRIEVED</span><span class="p">,</span>
1272
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SLURM_QUEUED</span><span class="p">,</span>
1273
+ <span class="p">]:</span>
1274
+ <span class="n">result</span> <span class="o">=</span> <span class="k">await</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">run_somewhere</span><span class="p">()</span>
1275
+ <span class="k">else</span><span class="p">:</span>
1276
+ <span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
1277
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> status: </span><span class="si">{</span><span class="n">status</span><span class="si">}</span><span class="s2"> was not executed&quot;</span>
1278
+ <span class="p">)</span>
1279
+
1280
+ <span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
1281
+ <span class="k">if</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1282
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
1283
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> node: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> has no registry entry&quot;</span>
1284
+ <span class="p">)</span>
1285
+ <span class="n">current_registry_entry</span> <span class="o">=</span> <span class="k">await</span> <span class="n">context</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">find_one</span><span class="p">(</span>
1286
+ <span class="n">NodeRegistry</span><span class="p">,</span> <span class="n">NodeRegistry</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">id</span>
1287
+ <span class="p">)</span>
1288
+ <span class="k">if</span> <span class="n">current_registry_entry</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1289
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
1290
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> node: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> registry entry disappeared&quot;</span>
1291
+ <span class="p">)</span>
1292
+
1293
+ <span class="k">if</span> <span class="p">(</span>
1294
+ <span class="n">current_registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span>
1295
+ <span class="ow">and</span> <span class="n">current_registry_entry</span><span class="o">.</span><span class="n">error</span>
1296
+ <span class="p">):</span>
1297
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">current_registry_entry</span><span class="o">.</span><span class="n">error</span><span class="p">)</span>
1298
+
1299
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
1300
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">current_registry_entry</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> node: </span><span class="si">{</span><span class="n">current_registry_entry</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> terminated with status </span><span class="si">{</span><span class="n">current_registry_entry</span><span class="o">.</span><span class="n">status</span><span class="si">}</span><span class="s2">&quot;</span>
1301
+ <span class="p">)</span>
1302
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
1303
+
1304
+ <span class="nd">@functools</span><span class="o">.</span><span class="n">wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
1305
+ <span class="k">def</span><span class="w"> </span><span class="nf">sync_wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">P</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">P</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
1306
+ <span class="kn">import</span><span class="w"> </span><span class="nn">asyncio</span>
1307
+
1308
+ <span class="n">update_kwargs</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
1309
+ <span class="c1"># Create Node with the remaining kwargs</span>
1310
+ <span class="n">execution_node</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
1311
+
1312
+ <span class="c1"># If it&#39;s an async function but called in a sync context, run it in the event loop</span>
1313
+ <span class="n">loop</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">get_event_loop</span><span class="p">()</span>
1314
+ <span class="n">status</span> <span class="o">=</span> <span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">execution_node</span><span class="o">.</span><span class="n">get_node_registry</span><span class="p">())</span>
1315
+ <span class="n">result</span> <span class="o">=</span> <span class="kc">None</span>
1316
+ <span class="k">if</span> <span class="n">status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
1317
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">execution_node</span><span class="o">.</span><span class="n">load_results</span><span class="p">()))</span>
1318
+ <span class="k">elif</span> <span class="n">status</span> <span class="ow">in</span> <span class="p">[</span>
1319
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SUBMITTED</span><span class="p">,</span>
1320
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">RETRIEVED</span><span class="p">,</span>
1321
+ <span class="n">TaskStatus</span><span class="o">.</span><span class="n">SLURM_QUEUED</span><span class="p">,</span>
1322
+ <span class="p">]:</span>
1323
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">execution_node</span><span class="o">.</span><span class="n">run_somewhere</span><span class="p">()))</span>
1324
+ <span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">COMPLETED</span><span class="p">:</span>
1325
+ <span class="k">if</span> <span class="p">(</span>
1326
+ <span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
1327
+ <span class="ow">and</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">FAILED</span>
1328
+ <span class="ow">and</span> <span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">error</span>
1329
+ <span class="p">):</span>
1330
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">execution_node</span><span class="o">.</span><span class="n">registry_entry</span><span class="o">.</span><span class="n">error</span><span class="p">)</span>
1331
+
1332
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
1333
+ <span class="sa">f</span><span class="s2">&quot;Task task_id: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">id</span><span class="si">}</span><span class="s2"> node: </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> terminated with status </span><span class="si">{</span><span class="n">execution_node</span><span class="o">.</span><span class="n">status</span><span class="si">}</span><span class="s2">&quot;</span>
1334
+ <span class="p">)</span>
1335
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">result</span><span class="p">)</span>
1336
+
1337
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">async_wrapper</span><span class="p">,</span> <span class="s2">&quot;is_node&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
1338
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">sync_wrapper</span><span class="p">,</span> <span class="s2">&quot;is_node&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
1339
+ <span class="c1"># Return the appropriate wrapper based on whether the function is async</span>
1340
+ <span class="k">if</span> <span class="n">is_async</span><span class="p">:</span>
1341
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">],</span> <span class="n">async_wrapper</span><span class="p">)</span>
1342
+ <span class="k">else</span><span class="p">:</span>
1343
+ <span class="k">return</span> <span class="n">cast</span><span class="p">(</span><span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">T</span><span class="p">],</span> <span class="n">sync_wrapper</span><span class="p">)</span>
1344
+
1345
+ <span class="nb">setattr</span><span class="p">(</span><span class="n">decorator</span><span class="p">,</span> <span class="s2">&quot;is_node&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
1346
+
1347
+ <span class="k">if</span> <span class="n">_func</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
1348
+ <span class="c1"># Called with parameters: @node(...)</span>
1349
+ <span class="k">return</span> <span class="n">decorator</span>
1350
+ <span class="k">else</span><span class="p">:</span>
1351
+ <span class="c1"># Called without parameters: @node</span>
1352
+ <span class="k">return</span> <span class="n">decorator</span><span class="p">(</span><span class="n">_func</span><span class="p">)</span></div>
1353
+
1354
+ </pre></div>
1355
+ </article>
1356
+ </div>
1357
+ <footer>
1358
+
1359
+ <div class="related-pages">
1360
+
1361
+
1362
+ </div>
1363
+ <div class="bottom-of-page">
1364
+ <div class="left-details">
1365
+ <div class="copyright">
1366
+ Copyright &#169; 2026, Wolfgang Wenzel
1367
+ </div>
1368
+ Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
1369
+
1370
+ <a href="https://github.com/pradyunsg/furo">Furo</a>
1371
+
1372
+ </div>
1373
+ <div class="right-details">
1374
+
1375
+ </div>
1376
+ </div>
1377
+
1378
+ </footer>
1379
+ </div>
1380
+ <aside class="toc-drawer no-toc">
1381
+
1382
+
1383
+
1384
+ </aside>
1385
+ </div>
1386
+ </div><script src="../../../_static/documentation_options.js?v=5929fcd5"></script>
1387
+ <script src="../../../_static/doctools.js?v=fd6eb6e6"></script>
1388
+ <script src="../../../_static/sphinx_highlight.js?v=6ffebe34"></script>
1389
+ <script src="../../../_static/scripts/furo.js?v=46bd48cc"></script>
1390
+ <script data-docs-built-at="2026-07-17 10:50:10 UTC" src="../../../_static/docs-build-badge.js?v=57cb9fc6"></script>
1391
+ </body>
1392
+ </html>