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,451 @@
1
+ import uuid
2
+ from typing import Dict, Iterator, Union, Tuple, KeysView, ValuesView, ItemsView, List, Optional, Any
3
+ from odmantic import Model, ObjectId, EmbeddedModel, Field, Reference
4
+ from simstack.core.asnyc_helper import async_helper
5
+ from simstack.models import simstack_model
6
+ from simstack.models.dataset_metadata import DataSetMetadata
7
+ from simstack.util.make_table import make_column_defs_instance
8
+ from simstack.util.make_table import make_table_entries_helper
9
+
10
+
11
+ @simstack_model
12
+ class DataSetSection(EmbeddedModel):
13
+ """
14
+ Represents a section of a dataset containing dictionaries of models.
15
+
16
+ A DataSetSection is a list of dictionaries where for each key, the values are of the same model type.
17
+
18
+ :ivar model_types: Dictionary mapping keys to model class names.
19
+ :type model_types: Dict[str, str]
20
+ :ivar data: Dictionary mapping names to dictionaries mapping keys to ObjectIds.
21
+ :type data: Dict[str, Dict[str, ObjectId]]
22
+ """
23
+
24
+ model_types: Dict[str, str] = Field(default_factory=dict)
25
+
26
+ data: Dict[str, Dict[str, ObjectId]] = Field(default_factory=dict)
27
+
28
+ column_defs: List[Dict] = Field(default_factory=list)
29
+ table_entries: List[List[Dict]] = Field(default_factory=list)
30
+
31
+ model_config = {"extra": "forbid"}
32
+
33
+ def _set_cache(self, cache: Dict[str, Dict[str, Model]]):
34
+ object.__getattribute__(self, "__dict__")["_cache"] = cache
35
+ return cache
36
+
37
+ def _get_cache(self) -> Dict[str, Dict[str, Model]]:
38
+ self_dict = object.__getattribute__(self, "__dict__")
39
+ cache = self_dict.get("_cache", None)
40
+ if cache is None:
41
+ cache = {}
42
+ cache = self._set_cache(cache)
43
+ return cache
44
+
45
+ def add_row(self, item: Dict[str, Optional[Model]], name: Optional[str] = None) -> None:
46
+ """
47
+ Add a dictionary of models to this section.
48
+
49
+ :param item: Dictionary of model instances to add.
50
+ :param name: Optional name for the item. If None, a UUID will be generated.
51
+ :raises ValueError: If the model types don't match the section's expected types.
52
+ :raises TypeError: If a non-None item value is not a Model instance.
53
+ """
54
+
55
+ if name is None:
56
+ name = str(uuid.uuid4())
57
+
58
+ cache = self._get_cache()
59
+ if name in cache:
60
+ raise ValueError(f"Item with name '{name}' already exists in section")
61
+
62
+ if not isinstance(item, dict):
63
+ raise TypeError("Item must be a dictionary")
64
+
65
+ # Type check: raise TypeError if an item which is not None is not a Model
66
+ for key, value in item.items():
67
+ if value is not None and not isinstance(value, Model):
68
+ raise TypeError(
69
+ f"Item with key '{key}' is not a Model instance: {type(value).__name__}"
70
+ )
71
+
72
+ filtered_item = {k: v for k, v in item.items() if v is not None}
73
+
74
+ current_item_types = {k: v.__class__.__name__ for k, v in filtered_item.items()}
75
+
76
+ # If this is the first item, we can partially or fully initialize model_types
77
+ # However, subsequent items might have new keys.
78
+ # The requirement says: "all items with the same key must be the same Model type"
79
+
80
+ for key, model_name in current_item_types.items():
81
+ if key in self.model_types:
82
+ if self.model_types[key] != model_name:
83
+ raise ValueError(
84
+ f"Model type for key '{key}' is {model_name}, but expected {self.model_types[key]}"
85
+ )
86
+ else:
87
+ self.model_types[key] = model_name
88
+
89
+ # Save all models to cache
90
+ cached_items = {}
91
+ for key, model in item.items():
92
+ if model is None:
93
+ continue
94
+ cached_items[key] = model
95
+
96
+ cache[name] = cached_items
97
+
98
+ async def make_column_defs(self):
99
+ """
100
+ Generate ag-grid column definitions for all model types in this section.
101
+ """
102
+
103
+ from simstack.util.importer import import_class_by_name
104
+ from simstack.core.context import context
105
+ engine = context.db
106
+ column_defs = []
107
+ cache = self._get_cache()
108
+ if not cache:
109
+ return column_defs
110
+
111
+ # Use model_types to determine columns.
112
+ for key, model_type in self.model_types.items():
113
+ model_instance = None
114
+ for row in cache.values():
115
+ if key in row:
116
+ model_instance = row[key]
117
+ break
118
+
119
+ if model_instance is None:
120
+ continue
121
+
122
+ model_columns = make_column_defs_instance(model_instance)
123
+ column_defs.extend(model_columns)
124
+
125
+ return column_defs
126
+
127
+ async def make_table_entries(self):
128
+ all_data = []
129
+ cache = self._get_cache()
130
+ for row in cache.values():
131
+ row_data = []
132
+ for key, model_type in self.model_types.items():
133
+ model_instance = row.get(key)
134
+ model_data = make_table_entries_helper(model_instance)
135
+ row_data.append(model_data)
136
+ all_data.append(row_data)
137
+ return all_data
138
+
139
+
140
+ async def save(self, db):
141
+ """
142
+ Save all models in the cache to the database and update data.
143
+ """
144
+ cache = self._get_cache()
145
+ for row_name, row_models in cache.items():
146
+ for model_key, model in row_models.items():
147
+ if model is not None:
148
+ await db.save_unchecked(model)
149
+
150
+ # Sync cache to data before saving
151
+ self.data = {
152
+ name: {k: v.id for k, v in row.items()}
153
+ for name, row in cache.items()
154
+ }
155
+
156
+ self.column_defs = await self.make_column_defs()
157
+ self.table_entries = await self.make_table_entries()
158
+
159
+ def get_item(self, name: str) -> Dict[str, Model]:
160
+ cache = self._get_cache()
161
+ if name not in cache:
162
+ raise KeyError(f"Item with name '{name}' not found")
163
+ return cache[name]
164
+
165
+ async def db_find_postprocess(self, db: "Database"):
166
+ await self.load_to_cache(db)
167
+
168
+ async def load_to_cache(self, db: "Database") -> None:
169
+ """
170
+ Load all items from the database into the cache assuming that data is already loaded.
171
+ """
172
+ from simstack.core.context import context
173
+ if db is None:
174
+ db = context.db
175
+ cache = self._get_cache()
176
+ for name, row in self.data.items():
177
+ cached_row = {}
178
+ for key, model_id in row.items():
179
+ model_type = self.model_types[key]
180
+ from simstack.util.importer import import_class_by_name
181
+ model_class = await import_class_by_name(model_type, db)
182
+ model_instance = await db.find_one(model_class, model_class.id == model_id)
183
+ if model_instance is None:
184
+ raise ValueError(f"Model with id {model_id} of type {model_type} not found")
185
+ cached_row[key] = model_instance
186
+
187
+ # Update cache
188
+ cache[name] = cached_row
189
+ self._set_cache(cache)
190
+
191
+ def __len__(self) -> int:
192
+ return len(self._get_cache())
193
+
194
+ def __iter__(self):
195
+ return iter(self._get_cache().items())
196
+
197
+ def __getitem__(self, name: str) -> Dict[str, Model]:
198
+ cache = self._get_cache()
199
+ if name in cache:
200
+ return cache[name]
201
+
202
+ raise KeyError(f"Item with name '{name}' not found")
203
+
204
+ def __setitem__(self, name: str, value: Dict[str, Optional[Model]]) -> None:
205
+ cache = self._get_cache()
206
+ if name in cache:
207
+ self.pop(name, None)
208
+
209
+ self.add_row(value, name=name)
210
+
211
+ def __delitem__(self, name: str) -> None:
212
+ cache = self._get_cache()
213
+ if name not in cache:
214
+ raise KeyError(f"Item with name '{name}' not found")
215
+ del cache[name]
216
+
217
+ def __contains__(self, name: str) -> bool:
218
+ return name in self._get_cache()
219
+
220
+ def get(self, name: str, default: Any = None) -> Any:
221
+ try:
222
+ return self[name]
223
+ except KeyError:
224
+ return default
225
+
226
+ def keys(self) -> KeysView[str]:
227
+ return self._get_cache().keys()
228
+
229
+ def values(self) -> ValuesView[Dict[str, Model]]:
230
+ return self._get_cache().values()
231
+
232
+ def items(self) -> ItemsView[str, Dict[str, Model]]:
233
+ return self._get_cache().items()
234
+
235
+ def clear(self) -> None:
236
+ self._set_cache({})
237
+
238
+ def pop(self, name: str, default: Any = ...) -> Any:
239
+ cache = self._get_cache()
240
+ if name not in cache:
241
+ if default is ...:
242
+ raise KeyError(f"Item with name '{name}' not found")
243
+ return default
244
+
245
+ return cache.pop(name)
246
+
247
+ def popitem(self) -> Tuple[str, Dict[str, Model]]:
248
+ cache = self._get_cache()
249
+ if not cache:
250
+ raise KeyError("popitem(): dictionary is empty")
251
+ return cache.popitem()
252
+
253
+ def update(self, other: Union[Dict[str, Dict[str, Optional[Model]]], "DataSetSection"]) -> None:
254
+ if isinstance(other, DataSetSection):
255
+ other_cache = other._get_cache()
256
+ for name, row in other_cache.items():
257
+ self[name] = row
258
+ else:
259
+ for name, row in other.items():
260
+ self[name] = row
261
+
262
+ def setdefault(self, name: str, default: Dict[str, Optional[Model]] = None) -> Dict[str, Model]:
263
+ cache = self._get_cache()
264
+ if name not in cache:
265
+ self[name] = default
266
+ return self[name]
267
+
268
+ def __repr__(self) -> str:
269
+ return f"DataSetSection(keys={list(self.model_types.keys())}, length={len(self)})"
270
+
271
+
272
+ @simstack_model
273
+ class DataSet(Model):
274
+ field_name: str = Field(default="dataset")
275
+ metadata: DataSetMetadata
276
+ sections: Dict[str, DataSetSection] = Field(default_factory=dict)
277
+
278
+ model_config = {"extra": "forbid"}
279
+
280
+ @property
281
+ def dataset_type(self) -> str:
282
+ return self.metadata.dataset_type
283
+
284
+ async def save(self, db):
285
+ structure = self.collect_structure()
286
+ # metadata.validate_dict currently expects Dict[str, List[str]]
287
+ # We might need to adjust it or pass something compatible.
288
+ # For now, let's just pass the keys of model_types as a list.
289
+ # Wait, DataSetTuple passes List[str] which are the model names in the tuple.
290
+ # For DataSet, maybe it should be the model names too, but we lose the keys.
291
+ # Let's see how validate_dict uses it.
292
+ ok = await self.metadata.validate_dict(structure)
293
+ if not ok:
294
+ raise ValueError("Metadata validation failed")
295
+
296
+ for key, section in self.sections.items():
297
+ await section.save(db)
298
+
299
+ await db.save_unchecked(self)
300
+
301
+ def collect_structure(self) -> Dict[str, Dict[str, str]]:
302
+ return {
303
+ section_name: section.model_types
304
+ for section_name, section in self.sections.items()
305
+ if section.data or len(section) > 0
306
+ }
307
+
308
+ def __getitem__(self, key: str) -> DataSetSection:
309
+ if key not in self.sections:
310
+ self.sections[key] = DataSetSection()
311
+ return self.sections[key]
312
+
313
+ def __setitem__(self, key: str, value: DataSetSection) -> None:
314
+ if key in self.sections:
315
+ raise KeyError(f"Section {key} already exists in dataset")
316
+ self.sections[key] = value
317
+
318
+ def __delitem__(self, key: str) -> None:
319
+ del self.sections[key]
320
+
321
+ def __len__(self) -> int:
322
+ return len(self.sections)
323
+
324
+ def __iter__(self) -> Iterator[str]:
325
+ return iter(self.sections)
326
+
327
+ def __contains__(self, key: str) -> bool:
328
+ return key in self.sections
329
+
330
+ def keys(self) -> KeysView[str]:
331
+ return self.sections.keys()
332
+
333
+ def values(self) -> ValuesView[DataSetSection]:
334
+ return self.sections.values()
335
+
336
+ def items(self) -> ItemsView[str, DataSetSection]:
337
+ return self.sections.items()
338
+
339
+ def get(self, key: str, default: DataSetSection = None) -> DataSetSection:
340
+ return self.sections.get(key, default)
341
+
342
+ def pop(self, key: str, default=None) -> DataSetSection:
343
+ return self.sections.pop(key, default)
344
+
345
+ def clear(self):
346
+ self.sections.clear()
347
+
348
+ def update(
349
+ self, other: Union[Dict[str, DataSetSection], "DataSet"] = None, **kwargs
350
+ ) -> None:
351
+ if other is not None:
352
+ if hasattr(other, "sections"):
353
+ self.sections.update(other.sections)
354
+ else:
355
+ self.sections.update(other)
356
+ self.sections.update(kwargs)
357
+
358
+ def setdefault(self, key: str, default: DataSetSection = None) -> DataSetSection:
359
+ return self.sections.setdefault(key, default)
360
+
361
+ @classmethod
362
+ def ui_schema(cls) -> dict:
363
+ return {
364
+ "ui:field": "DataSetField",
365
+ "metadata": {"ui:widget": "hidden"},
366
+ "sections": {"ui:widget": "hidden"},
367
+ }
368
+
369
+
370
+ class DataSetSelectionField(EmbeddedModel):
371
+ section_name: str = Field(default="default")
372
+ indices: List[int] = Field(default_factory=list)
373
+
374
+ @simstack_model
375
+ class DataSetSelection(Model):
376
+ field_name: str = Field(default="dataset_selection")
377
+ dataset_id: ObjectId
378
+ dataset_selection_fields: List[DataSetSelectionField] = Field(default_factory=list)
379
+
380
+ async def get_dataset(self):
381
+ from simstack.core.context import context
382
+ return await context.db.find_one(DataSet, DataSet.id == self.dataset_id)
383
+
384
+ @async_helper
385
+ async def get_selected_elements(self, section_name: str = None) -> List[Tuple[Model, ...]]:
386
+ """
387
+ Retrieve all selected model groups from the dataset.
388
+
389
+ :param section_name: Optional section name to filter results. If None, returns all sections.
390
+ :return: List of tuples of model instances for all selected elements
391
+ """
392
+ from simstack.core.context import context
393
+ db = context.db
394
+ dataset = await db.find_one(DataSet, DataSet.id == self.dataset_id)
395
+
396
+ if dataset is None:
397
+ raise ValueError(f"Dataset with id {self.dataset_id} not found")
398
+
399
+ selected_elements = []
400
+ for selection_field in self.dataset_selection_fields:
401
+ if section_name is not None and selection_field.section_name != section_name:
402
+ continue
403
+
404
+ section = dataset.sections.get(selection_field.section_name)
405
+ if section is None:
406
+ raise ValueError(f"Section {selection_field.section_name} not found in dataset")
407
+
408
+ for index in selection_field.indices:
409
+ if index >= len(section):
410
+ raise IndexError(
411
+ f"Index {index} out of range for section {selection_field.section_name} with {len(section)} elements"
412
+ )
413
+ model_group = section.get_model_group(index)
414
+ selected_elements.append(model_group)
415
+
416
+ return selected_elements
417
+
418
+ async def __aiter__(self, section_name: str = None):
419
+ """
420
+ Async iterator over all selected model groups.
421
+
422
+ :param section_name: Optional section name to filter results. If None, returns all sections.
423
+ :return: Async iterator yielding tuples of model instances
424
+ """
425
+ from simstack.core.context import context
426
+ db = context.db
427
+ dataset = await db.find_one(DataSet, DataSet.id == self.dataset_id)
428
+
429
+ if dataset is None:
430
+ raise ValueError(f"Dataset with id {self.dataset_id} not found")
431
+
432
+ for selection_field in self.dataset_selection_fields:
433
+ if section_name is not None and selection_field.section_name != section_name:
434
+ continue
435
+
436
+ section = dataset.sections.get(selection_field.section_name)
437
+ if section is None:
438
+ raise ValueError(f"Section {selection_field.section_name} not found in dataset")
439
+
440
+ for index in selection_field.indices:
441
+ if index >= len(section):
442
+ raise IndexError(
443
+ f"Index {index} out of range for section {selection_field.section_name} with {len(section)} elements"
444
+ )
445
+ yield section.get_model_group(index)
446
+
447
+ @classmethod
448
+ def ui_schema(cls) -> dict:
449
+ return {
450
+ "ui:field": "DataSetSelectionField",
451
+ }