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.
- simstack/__init__.py +0 -0
- simstack/_version.py +24 -0
- simstack/core/__init__.py +0 -0
- simstack/core/artifacts.py +406 -0
- simstack/core/asnyc_helper.py +14 -0
- simstack/core/config_file.py +60 -0
- simstack/core/context.py +283 -0
- simstack/core/definitions.py +22 -0
- simstack/core/engine.py +115 -0
- simstack/core/find_simstack_modules.py +41 -0
- simstack/core/hash.py +179 -0
- simstack/core/node.py +1137 -0
- simstack/core/node_claim.py +31 -0
- simstack/core/node_runner.py +362 -0
- simstack/core/process_results.py +102 -0
- simstack/core/recompute_artifacts.py +117 -0
- simstack/core/reset_db.py +12 -0
- simstack/core/resource_assignment.py +222 -0
- simstack/core/resources.py +90 -0
- simstack/core/route_table.py +24 -0
- simstack/core/run_docker.py +109 -0
- simstack/core/run_node.py +71 -0
- simstack/core/runner.py +169 -0
- simstack/core/services/__init__.py +11 -0
- simstack/core/services/base_service.py +191 -0
- simstack/core/services/file_transfer_service.py +117 -0
- simstack/core/services/git_restart_service.py +12 -0
- simstack/core/services/git_uv_update_service.py +105 -0
- simstack/core/services/node_execution_service.py +182 -0
- simstack/core/services/resource_branch_monitor_service.py +71 -0
- simstack/core/services/runner_cleanup_service.py +149 -0
- simstack/core/services/runner_manager.py +163 -0
- simstack/core/services/runner_status_service.py +10 -0
- simstack/core/services/slurm_status_service.py +67 -0
- simstack/core/services/stop_check_service.py +27 -0
- simstack/core/services/timeout_restart_service.py +26 -0
- simstack/core/simstack_result.py +39 -0
- simstack/core/submit_node.py +217 -0
- simstack/core/task_id.py +22 -0
- simstack/methods/__init__.py +0 -0
- simstack/methods/archive_files.py +292 -0
- simstack/methods/fire_and_forget_runner.py +113 -0
- simstack/methods/generate_test.py +125 -0
- simstack/methods/get_file.py +26 -0
- simstack/methods/mass_runner.py +154 -0
- simstack/methods/multiple_executor.py +307 -0
- simstack/methods/switch_git.py +16 -0
- simstack/methods/upload_helpers.py +81 -0
- simstack/models/__init__.py +74 -0
- simstack/models/array_list.py +21 -0
- simstack/models/array_storage.py +83 -0
- simstack/models/artifact_models.py +127 -0
- simstack/models/base_lists.py +51 -0
- simstack/models/base_types.py +209 -0
- simstack/models/charts_artifact.py +690 -0
- simstack/models/dataset.py +451 -0
- simstack/models/dataset_metadata.py +390 -0
- simstack/models/datasettuple.py +587 -0
- simstack/models/file_instance.py +150 -0
- simstack/models/file_list.py +45 -0
- simstack/models/files.py +424 -0
- simstack/models/fire_and_forget_result.py +19 -0
- simstack/models/images2d.py +113 -0
- simstack/models/log_entry_model.py +37 -0
- simstack/models/models.py +52 -0
- simstack/models/named_data_reference.py +36 -0
- simstack/models/node_registry.py +96 -0
- simstack/models/pandas_model.py +239 -0
- simstack/models/parameters.py +402 -0
- simstack/models/pickle_models.py +300 -0
- simstack/models/project.py +13 -0
- simstack/models/resource_assignment.py +170 -0
- simstack/models/resource_definition.py +125 -0
- simstack/models/runner_model.py +39 -0
- simstack/models/simple_table.py +79 -0
- simstack/models/simstack_model.py +97 -0
- simstack/models/slurm_info.py +17 -0
- simstack/models/table_artifact.py +87 -0
- simstack/models/tag.py +12 -0
- simstack/models/unused_test_file.py +5 -0
- simstack/simstack_marker.com +1 -0
- simstack/static/docs/.buildinfo +4 -0
- simstack/static/docs/_images/GUI Concept.webp +0 -0
- simstack/static/docs/_modules/index.html +434 -0
- simstack/static/docs/_modules/simstack/core/artifacts.html +743 -0
- simstack/static/docs/_modules/simstack/core/asnyc_helper.html +330 -0
- simstack/static/docs/_modules/simstack/core/config_file.html +379 -0
- simstack/static/docs/_modules/simstack/core/definitions.html +341 -0
- simstack/static/docs/_modules/simstack/core/engine.html +437 -0
- simstack/static/docs/_modules/simstack/core/find_simstack_modules.html +360 -0
- simstack/static/docs/_modules/simstack/core/hash.html +528 -0
- simstack/static/docs/_modules/simstack/core/node.html +1392 -0
- simstack/static/docs/_modules/simstack/core/node_claim.html +347 -0
- simstack/static/docs/_modules/simstack/core/node_runner.html +711 -0
- simstack/static/docs/_modules/simstack/core/process_results.html +418 -0
- simstack/static/docs/_modules/simstack/core/recompute_artifacts.html +433 -0
- simstack/static/docs/_modules/simstack/core/reset_db.html +328 -0
- simstack/static/docs/_modules/simstack/core/resource_assignment.html +553 -0
- simstack/static/docs/_modules/simstack/core/resources.html +424 -0
- simstack/static/docs/_modules/simstack/core/route_table.html +349 -0
- simstack/static/docs/_modules/simstack/core/run_docker.html +425 -0
- simstack/static/docs/_modules/simstack/core/run_node.html +390 -0
- simstack/static/docs/_modules/simstack/core/runner.html +491 -0
- simstack/static/docs/_modules/simstack/core/services/base_service.html +522 -0
- simstack/static/docs/_modules/simstack/core/services/file_transfer_service.html +436 -0
- simstack/static/docs/_modules/simstack/core/services/git_restart_service.html +331 -0
- simstack/static/docs/_modules/simstack/core/services/git_uv_update_service.html +427 -0
- simstack/static/docs/_modules/simstack/core/services/node_execution_service.html +507 -0
- simstack/static/docs/_modules/simstack/core/services/resource_branch_monitor_service.html +390 -0
- simstack/static/docs/_modules/simstack/core/services/runner_cleanup_service.html +468 -0
- simstack/static/docs/_modules/simstack/core/services/runner_manager.html +485 -0
- simstack/static/docs/_modules/simstack/core/services/runner_status_service.html +329 -0
- simstack/static/docs/_modules/simstack/core/services/slurm_status_service.html +386 -0
- simstack/static/docs/_modules/simstack/core/services/stop_check_service.html +346 -0
- simstack/static/docs/_modules/simstack/core/services/timeout_restart_service.html +345 -0
- simstack/static/docs/_modules/simstack/core/simstack_result.html +355 -0
- simstack/static/docs/_modules/simstack/core/submit_node.html +536 -0
- simstack/static/docs/_modules/simstack/core/task_id.html +344 -0
- simstack/static/docs/_modules/simstack/methods/archive_files.html +598 -0
- simstack/static/docs/_modules/simstack/methods/fire_and_forget_runner.html +432 -0
- simstack/static/docs/_modules/simstack/methods/generate_test.html +443 -0
- simstack/static/docs/_modules/simstack/methods/get_file.html +342 -0
- simstack/static/docs/_modules/simstack/methods/mass_runner.html +476 -0
- simstack/static/docs/_modules/simstack/methods/multiple_executor.html +674 -0
- simstack/static/docs/_modules/simstack/methods/switch_git.html +332 -0
- simstack/static/docs/_modules/simstack/methods/upload_helpers.html +403 -0
- simstack/static/docs/_modules/simstack/models/array_list.html +337 -0
- simstack/static/docs/_modules/simstack/models/array_storage.html +417 -0
- simstack/static/docs/_modules/simstack/models/base_lists.html +374 -0
- simstack/static/docs/_modules/simstack/models/base_types.html +588 -0
- simstack/static/docs/_modules/simstack/models/charts_artifact.html +1035 -0
- simstack/static/docs/_modules/simstack/models/dataset.html +866 -0
- simstack/static/docs/_modules/simstack/models/dataset_metadata.html +711 -0
- simstack/static/docs/_modules/simstack/models/datasettuple.html +1005 -0
- simstack/static/docs/_modules/simstack/models/file_instance.html +472 -0
- simstack/static/docs/_modules/simstack/models/file_list.html +367 -0
- simstack/static/docs/_modules/simstack/models/files.html +773 -0
- simstack/static/docs/_modules/simstack/models/fire_and_forget_result.html +335 -0
- simstack/static/docs/_modules/simstack/models/images2d.html +447 -0
- simstack/static/docs/_modules/simstack/models/log_entry_model.html +356 -0
- simstack/static/docs/_modules/simstack/models/models.html +374 -0
- simstack/static/docs/_modules/simstack/models/named_data_reference.html +355 -0
- simstack/static/docs/_modules/simstack/models/node_registry.html +415 -0
- simstack/static/docs/_modules/simstack/models/pandas_model.html +570 -0
- simstack/static/docs/_modules/simstack/models/parameters.html +739 -0
- simstack/static/docs/_modules/simstack/models/pickle_models.html +631 -0
- simstack/static/docs/_modules/simstack/models/project.html +329 -0
- simstack/static/docs/_modules/simstack/models/resource_assignment.html +501 -0
- simstack/static/docs/_modules/simstack/models/resource_definition.html +477 -0
- simstack/static/docs/_modules/simstack/models/runner_model.html +361 -0
- simstack/static/docs/_modules/simstack/models/simple_table.html +413 -0
- simstack/static/docs/_modules/simstack/models/simstack_model.html +416 -0
- simstack/static/docs/_modules/simstack/models/slurm_info.html +333 -0
- simstack/static/docs/_modules/simstack/models/table_artifact.html +406 -0
- simstack/static/docs/_modules/simstack/models/tag.html +328 -0
- simstack/static/docs/_modules/simstack/tables/model_table.html +519 -0
- simstack/static/docs/_modules/simstack/tables/node_children.html +538 -0
- simstack/static/docs/_modules/simstack/tables/node_table.html +854 -0
- simstack/static/docs/_modules/simstack/tables/table_builder.html +642 -0
- simstack/static/docs/_modules/simstack/util/async_zip_utils.html +337 -0
- simstack/static/docs/_modules/simstack/util/b64mixin.html +339 -0
- simstack/static/docs/_modules/simstack/util/cleaned_json_schema.html +336 -0
- simstack/static/docs/_modules/simstack/util/config_reader.html +498 -0
- simstack/static/docs/_modules/simstack/util/custom_model_dump.html +391 -0
- simstack/static/docs/_modules/simstack/util/database_information.html +488 -0
- simstack/static/docs/_modules/simstack/util/db.html +1392 -0
- simstack/static/docs/_modules/simstack/util/db_logger.html +448 -0
- simstack/static/docs/_modules/simstack/util/default_from_dict.html +376 -0
- simstack/static/docs/_modules/simstack/util/directory_iterator.html +553 -0
- simstack/static/docs/_modules/simstack/util/docstring_parser.html +526 -0
- simstack/static/docs/_modules/simstack/util/file_hashing.html +394 -0
- simstack/static/docs/_modules/simstack/util/file_transfer_client.html +791 -0
- simstack/static/docs/_modules/simstack/util/files.html +733 -0
- simstack/static/docs/_modules/simstack/util/find_python_files.html +349 -0
- simstack/static/docs/_modules/simstack/util/generate_ui_schema.html +396 -0
- simstack/static/docs/_modules/simstack/util/generic_list_mixin.html +487 -0
- simstack/static/docs/_modules/simstack/util/get_module_path.html +336 -0
- simstack/static/docs/_modules/simstack/util/git_pull.html +381 -0
- simstack/static/docs/_modules/simstack/util/git_repository_status.html +411 -0
- simstack/static/docs/_modules/simstack/util/import_module.html +377 -0
- simstack/static/docs/_modules/simstack/util/importer.html +637 -0
- simstack/static/docs/_modules/simstack/util/init_data_source.html +357 -0
- simstack/static/docs/_modules/simstack/util/make_graph.html +423 -0
- simstack/static/docs/_modules/simstack/util/make_table.html +1171 -0
- simstack/static/docs/_modules/simstack/util/mappings.html +378 -0
- simstack/static/docs/_modules/simstack/util/minimal_route_finder.html +388 -0
- simstack/static/docs/_modules/simstack/util/mock_db.html +472 -0
- simstack/static/docs/_modules/simstack/util/module_path_checker.html +354 -0
- simstack/static/docs/_modules/simstack/util/object_list_mixin.html +649 -0
- simstack/static/docs/_modules/simstack/util/path_manager.html +566 -0
- simstack/static/docs/_modules/simstack/util/project_root_finder.html +357 -0
- simstack/static/docs/_modules/simstack/util/queue_watcher.html +593 -0
- simstack/static/docs/_modules/simstack/util/resource_config.html +532 -0
- simstack/static/docs/_modules/simstack/util/route_finder.html +390 -0
- simstack/static/docs/_modules/simstack/util/runner_util.html +487 -0
- simstack/static/docs/_modules/simstack/util/runner_utils.html +468 -0
- simstack/static/docs/_modules/simstack/util/safe_code_executor.html +510 -0
- simstack/static/docs/_modules/simstack/util/sample_config.html +414 -0
- simstack/static/docs/_modules/simstack/util/sensitive_content_filter.html +364 -0
- simstack/static/docs/_modules/simstack/util/setup_logging.html +365 -0
- simstack/static/docs/_modules/simstack/util/submit_to_watchdog.html +425 -0
- simstack/static/docs/_modules/simstack/util/toml_reader.html +482 -0
- simstack/static/docs/_modules/simstack/util/transform_file_name.html +357 -0
- simstack/static/docs/_modules/simstack/util/ui_tools.html +541 -0
- simstack/static/docs/_sources/architecture.rst.txt +25 -0
- simstack/static/docs/_sources/array_lists.rst.txt +60 -0
- simstack/static/docs/_sources/ci_pipeline.rst.txt +34 -0
- simstack/static/docs/_sources/data.rst.txt +175 -0
- simstack/static/docs/_sources/database_migrations.rst.txt +310 -0
- simstack/static/docs/_sources/datasets.rst.txt +93 -0
- simstack/static/docs/_sources/developer_guide.rst.txt +25 -0
- simstack/static/docs/_sources/docker_nodes.rst.txt +149 -0
- simstack/static/docs/_sources/files.rst.txt +159 -0
- simstack/static/docs/_sources/fire_and_forget_runner.rst.txt +67 -0
- simstack/static/docs/_sources/index.rst.txt +25 -0
- simstack/static/docs/_sources/installation.rst.txt +213 -0
- simstack/static/docs/_sources/lists.rst.txt +111 -0
- simstack/static/docs/_sources/mass_runner.rst.txt +91 -0
- simstack/static/docs/_sources/misc.rst.txt +106 -0
- simstack/static/docs/_sources/overview.rst.txt +91 -0
- simstack/static/docs/_sources/recovery.rst.txt +38 -0
- simstack/static/docs/_sources/resource_config.rst.txt +141 -0
- simstack/static/docs/_sources/simstack/modules/modules.rst.txt +7 -0
- simstack/static/docs/_sources/simstack/modules/simstack.core.rst.txt +205 -0
- simstack/static/docs/_sources/simstack/modules/simstack.core.services.rst.txt +109 -0
- simstack/static/docs/_sources/simstack/modules/simstack.methods.rst.txt +77 -0
- simstack/static/docs/_sources/simstack/modules/simstack.models.rst.txt +261 -0
- simstack/static/docs/_sources/simstack/modules/simstack.rst.txt +22 -0
- simstack/static/docs/_sources/simstack/modules/simstack.tables.rst.txt +45 -0
- simstack/static/docs/_sources/simstack/modules/simstack.util.rst.txt +381 -0
- simstack/static/docs/_sources/submit.rst.txt +141 -0
- simstack/static/docs/_sources/tables.rst.txt +50 -0
- simstack/static/docs/_sources/testing_complex_nodes.rst.txt +92 -0
- simstack/static/docs/_sources/ui_documentation.rst.txt +272 -0
- simstack/static/docs/_sources/workflows.rst.txt +446 -0
- simstack/static/docs/_static/base-stemmer.js +476 -0
- simstack/static/docs/_static/basic.css +906 -0
- simstack/static/docs/_static/cobalt2-theme.css +1 -0
- simstack/static/docs/_static/debug.css +69 -0
- simstack/static/docs/_static/docs-build-badge.css +51 -0
- simstack/static/docs/_static/docs-build-badge.js +51 -0
- simstack/static/docs/_static/doctools.js +150 -0
- simstack/static/docs/_static/documentation_options.js +13 -0
- simstack/static/docs/_static/english-stemmer.js +1066 -0
- simstack/static/docs/_static/file.png +0 -0
- simstack/static/docs/_static/language_data.js +13 -0
- simstack/static/docs/_static/minus.png +0 -0
- simstack/static/docs/_static/plus.png +0 -0
- simstack/static/docs/_static/pygments.css +250 -0
- simstack/static/docs/_static/scripts/furo-extensions.js +0 -0
- simstack/static/docs/_static/scripts/furo.js +3 -0
- simstack/static/docs/_static/scripts/furo.js.LICENSE.txt +7 -0
- simstack/static/docs/_static/scripts/furo.js.map +1 -0
- simstack/static/docs/_static/searchtools.js +693 -0
- simstack/static/docs/_static/skeleton.css +296 -0
- simstack/static/docs/_static/sphinx_highlight.js +159 -0
- simstack/static/docs/_static/styles/furo-extensions.css +2 -0
- simstack/static/docs/_static/styles/furo-extensions.css.map +1 -0
- simstack/static/docs/_static/styles/furo.css +2 -0
- simstack/static/docs/_static/styles/furo.css.map +1 -0
- simstack/static/docs/architecture.html +340 -0
- simstack/static/docs/array_lists.html +678 -0
- simstack/static/docs/ci_pipeline.html +385 -0
- simstack/static/docs/data.html +545 -0
- simstack/static/docs/database_migrations.html +652 -0
- simstack/static/docs/datasets.html +1268 -0
- simstack/static/docs/developer_guide.html +359 -0
- simstack/static/docs/docker_nodes.html +503 -0
- simstack/static/docs/files.html +718 -0
- simstack/static/docs/fire_and_forget_runner.html +641 -0
- simstack/static/docs/genindex.html +6390 -0
- simstack/static/docs/index.html +516 -0
- simstack/static/docs/installation.html +553 -0
- simstack/static/docs/lists.html +478 -0
- simstack/static/docs/mass_runner.html +481 -0
- simstack/static/docs/misc.html +454 -0
- simstack/static/docs/objects.inv +0 -0
- simstack/static/docs/overview.html +469 -0
- simstack/static/docs/py-modindex.html +1111 -0
- simstack/static/docs/recovery.html +371 -0
- simstack/static/docs/resource_config.html +590 -0
- simstack/static/docs/search.html +327 -0
- simstack/static/docs/searchindex.js +1 -0
- simstack/static/docs/simstack/modules/modules.html +489 -0
- simstack/static/docs/simstack/modules/simstack.core.html +1883 -0
- simstack/static/docs/simstack/modules/simstack.core.services.html +698 -0
- simstack/static/docs/simstack/modules/simstack.html +3060 -0
- simstack/static/docs/simstack/modules/simstack.methods.html +1150 -0
- simstack/static/docs/simstack/modules/simstack.models.html +13113 -0
- simstack/static/docs/simstack/modules/simstack.tables.html +635 -0
- simstack/static/docs/simstack/modules/simstack.util.html +3320 -0
- simstack/static/docs/submit.html +487 -0
- simstack/static/docs/tables.html +539 -0
- simstack/static/docs/testing_complex_nodes.html +458 -0
- simstack/static/docs/ui_documentation.html +788 -0
- simstack/static/docs/workflows.html +766 -0
- simstack/tables/__init__.py +0 -0
- simstack/tables/model_table.py +191 -0
- simstack/tables/node_children.py +219 -0
- simstack/tables/node_table.py +517 -0
- simstack/tables/table_builder.py +314 -0
- simstack/util/__init__.py +0 -0
- simstack/util/async_zip_utils.py +18 -0
- simstack/util/b64mixin.py +23 -0
- simstack/util/cleaned_json_schema.py +20 -0
- simstack/util/config_reader.py +179 -0
- simstack/util/custom_model_dump.py +75 -0
- simstack/util/database_information.py +160 -0
- simstack/util/db.py +1013 -0
- simstack/util/db_logger.py +117 -0
- simstack/util/default_from_dict.py +57 -0
- simstack/util/directory_iterator.py +216 -0
- simstack/util/docstring_parser.py +186 -0
- simstack/util/file_hashing.py +72 -0
- simstack/util/file_transfer_client.py +427 -0
- simstack/util/files.py +396 -0
- simstack/util/find_python_files.py +33 -0
- simstack/util/generate_ui_schema.py +80 -0
- simstack/util/generic_list_mixin.py +120 -0
- simstack/util/geometry_utils.py +118 -0
- simstack/util/get_module_path.py +20 -0
- simstack/util/git_pull.py +65 -0
- simstack/util/git_repository_status.py +95 -0
- simstack/util/import_module.py +63 -0
- simstack/util/importer.py +312 -0
- simstack/util/init_data_source.py +41 -0
- simstack/util/make_graph.py +107 -0
- simstack/util/make_table.py +837 -0
- simstack/util/mappings.py +41 -0
- simstack/util/minimal_route_finder.py +72 -0
- simstack/util/mock_db.py +144 -0
- simstack/util/module_path_checker.py +38 -0
- simstack/util/object_list_mixin.py +282 -0
- simstack/util/path_manager.py +223 -0
- simstack/util/project_root_finder.py +41 -0
- simstack/util/queue_watcher.py +262 -0
- simstack/util/resource_config.py +198 -0
- simstack/util/route_finder.py +74 -0
- simstack/util/runner_util.py +166 -0
- simstack/util/runner_utils.py +143 -0
- simstack/util/safe_code_executor.py +194 -0
- simstack/util/sample_config.py +98 -0
- simstack/util/sensitive_content_filter.py +48 -0
- simstack/util/setup_logging.py +49 -0
- simstack/util/submit_to_watchdog.py +106 -0
- simstack/util/toml_reader.py +142 -0
- simstack/util/transform_file_name.py +41 -0
- simstack/util/ui_tools.py +213 -0
- simstack-2.0.1.dist-info/METADATA +454 -0
- simstack-2.0.1.dist-info/RECORD +354 -0
- simstack-2.0.1.dist-info/WHEEL +5 -0
- simstack-2.0.1.dist-info/entry_points.txt +12 -0
- simstack-2.0.1.dist-info/licenses/LICENSE +21 -0
- simstack-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from odmantic import Model, Field, ObjectId
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Project(Model):
|
|
7
|
+
field_name: str = Field(unique=True)
|
|
8
|
+
description: Optional[str] = None
|
|
9
|
+
tag_ids: List[ObjectId] = Field(default_factory=list)
|
|
10
|
+
|
|
11
|
+
model_config = {
|
|
12
|
+
"collection": "projects",
|
|
13
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Optional, ClassVar, Dict, Any
|
|
3
|
+
|
|
4
|
+
from odmantic import Field, Model, EmbeddedModel
|
|
5
|
+
from pydantic import field_validator, model_validator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SlurmParametersPatch(EmbeddedModel):
|
|
9
|
+
nodes: Optional[int] = Field(default=None, ge=1)
|
|
10
|
+
tasks: Optional[int] = Field(default=None, ge=1)
|
|
11
|
+
tasks_per_node: Optional[int] = Field(default=None, ge=1)
|
|
12
|
+
cpus_per_task: Optional[int] = Field(default=None, ge=1)
|
|
13
|
+
mem: Optional[str] = None
|
|
14
|
+
mem_per_cpu: Optional[str] = None
|
|
15
|
+
time: Optional[str] = None
|
|
16
|
+
begin: Optional[str] = None
|
|
17
|
+
partition: Optional[str] = None
|
|
18
|
+
qos: Optional[str] = None
|
|
19
|
+
job_name: Optional[str] = None
|
|
20
|
+
output: Optional[str] = None
|
|
21
|
+
error: Optional[str] = None
|
|
22
|
+
mail_type: Optional[str] = None
|
|
23
|
+
mail_user: Optional[str] = None
|
|
24
|
+
gres: Optional[str] = None
|
|
25
|
+
account: Optional[str] = None
|
|
26
|
+
priority: Optional[int] = None
|
|
27
|
+
reservation: Optional[str] = None
|
|
28
|
+
constraint: Optional[str] = None
|
|
29
|
+
exclusive: Optional[bool] = None
|
|
30
|
+
nice: Optional[int] = None
|
|
31
|
+
dependency: Optional[str] = None
|
|
32
|
+
array: Optional[str] = None
|
|
33
|
+
startup_commands: Optional[list[str]] = None
|
|
34
|
+
chdir: Optional[str] = None
|
|
35
|
+
export: Optional[str] = None
|
|
36
|
+
signal: Optional[str] = None
|
|
37
|
+
requeue: Optional[bool] = None
|
|
38
|
+
no_requeue: Optional[bool] = None
|
|
39
|
+
|
|
40
|
+
model_config: ClassVar[Dict[str, Any]] = {
|
|
41
|
+
"extra": "forbid",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ResourceAssignmentRule(Model):
|
|
46
|
+
name: str = Field(unique=True)
|
|
47
|
+
regex_pattern: str
|
|
48
|
+
priority: int = Field(default=0)
|
|
49
|
+
enabled: bool = Field(default=True)
|
|
50
|
+
resource_str: Optional[str] = None
|
|
51
|
+
queue: Optional[str] = None
|
|
52
|
+
slurm_parameters_patch: Dict[str, Any] = Field(default_factory=dict)
|
|
53
|
+
description: Optional[str] = ""
|
|
54
|
+
|
|
55
|
+
model_config = {"collection": "resource_assignment_rule"}
|
|
56
|
+
|
|
57
|
+
@field_validator("name", "regex_pattern", mode="before")
|
|
58
|
+
@classmethod
|
|
59
|
+
def _strip_required_strings(cls, value):
|
|
60
|
+
if value is None:
|
|
61
|
+
return value
|
|
62
|
+
return str(value).strip()
|
|
63
|
+
|
|
64
|
+
@field_validator("resource_str", "queue", "description", mode="before")
|
|
65
|
+
@classmethod
|
|
66
|
+
def _strip_optional_strings(cls, value):
|
|
67
|
+
if value is None:
|
|
68
|
+
return None
|
|
69
|
+
normalized = str(value).strip()
|
|
70
|
+
return normalized or None
|
|
71
|
+
|
|
72
|
+
@field_validator("regex_pattern", mode="after")
|
|
73
|
+
@classmethod
|
|
74
|
+
def _validate_regex_pattern(cls, value: str) -> str:
|
|
75
|
+
if not value:
|
|
76
|
+
raise ValueError("Path pattern must not be empty")
|
|
77
|
+
try:
|
|
78
|
+
re.compile(cls.pattern_to_regex(value))
|
|
79
|
+
except ValueError:
|
|
80
|
+
raise
|
|
81
|
+
except re.error as exc:
|
|
82
|
+
raise ValueError(f"Invalid path pattern: {exc}") from exc
|
|
83
|
+
return value
|
|
84
|
+
|
|
85
|
+
@model_validator(mode="after")
|
|
86
|
+
def _validate_has_effect(self):
|
|
87
|
+
has_slurm_patch = bool(self.slurm_parameters_patch)
|
|
88
|
+
if not any([self.resource_str, self.queue, has_slurm_patch]):
|
|
89
|
+
raise ValueError(
|
|
90
|
+
"ResourceAssignmentRule must set at least one of resource_str, queue, or slurm_parameters_patch"
|
|
91
|
+
)
|
|
92
|
+
return self
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def normalize_pattern(pattern: str) -> str:
|
|
96
|
+
normalized = (pattern or "").strip()
|
|
97
|
+
if normalized.startswith("."):
|
|
98
|
+
without_leading_dots = normalized.lstrip(".")
|
|
99
|
+
if without_leading_dots and "." not in without_leading_dots:
|
|
100
|
+
return f"*.{without_leading_dots}"
|
|
101
|
+
return without_leading_dots
|
|
102
|
+
return normalized
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def _pattern_segments(cls, pattern: str) -> list[str]:
|
|
106
|
+
return [
|
|
107
|
+
segment for segment in cls.normalize_pattern(pattern).split(".") if segment
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def _segment_to_regex(segment: str) -> str:
|
|
112
|
+
return "".join("[^.]*" if char == "*" else re.escape(char) for char in segment)
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def pattern_to_regex(cls, pattern: str) -> str:
|
|
116
|
+
segments = cls._pattern_segments(pattern)
|
|
117
|
+
if not segments:
|
|
118
|
+
raise ValueError("Path pattern must not be empty")
|
|
119
|
+
if segments == ["*"]:
|
|
120
|
+
return r"[^.]+(?:\.[^.]+)*"
|
|
121
|
+
|
|
122
|
+
regex_parts: list[str] = []
|
|
123
|
+
for index, segment in enumerate(segments):
|
|
124
|
+
if segment == "*":
|
|
125
|
+
regex_parts.append(r"(?:[^.]+\.)*" if index == 0 else r"(?:\.[^.]+)*")
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
segment_regex = cls._segment_to_regex(segment)
|
|
129
|
+
previous_is_leading_wildcard = index == 1 and segments[0] == "*"
|
|
130
|
+
if index == 0 or previous_is_leading_wildcard:
|
|
131
|
+
regex_parts.append(segment_regex)
|
|
132
|
+
else:
|
|
133
|
+
regex_parts.append(r"\." + segment_regex)
|
|
134
|
+
|
|
135
|
+
return "".join(regex_parts)
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def pattern_specificity_score(cls, pattern: str) -> int:
|
|
139
|
+
segments = cls._pattern_segments(pattern)
|
|
140
|
+
literal_segment_count = sum(1 for segment in segments if segment != "*")
|
|
141
|
+
literal_char_count = sum(len(segment.replace("*", "")) for segment in segments)
|
|
142
|
+
wildcard_count = sum(segment.count("*") for segment in segments)
|
|
143
|
+
return (
|
|
144
|
+
literal_segment_count * 10000
|
|
145
|
+
+ literal_char_count * 100
|
|
146
|
+
+ len(segments)
|
|
147
|
+
- wildcard_count
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
@classmethod
|
|
151
|
+
def matches_call_path(cls, pattern: str, normalized_call_path: str) -> bool:
|
|
152
|
+
return (
|
|
153
|
+
re.fullmatch(cls.pattern_to_regex(pattern), normalized_call_path)
|
|
154
|
+
is not None
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
@field_validator("slurm_parameters_patch", mode="before")
|
|
158
|
+
@classmethod
|
|
159
|
+
def _normalize_slurm_patch(cls, value):
|
|
160
|
+
if value is None:
|
|
161
|
+
return {}
|
|
162
|
+
if isinstance(value, SlurmParametersPatch):
|
|
163
|
+
return value.model_dump(exclude_none=True)
|
|
164
|
+
if isinstance(value, dict):
|
|
165
|
+
return SlurmParametersPatch.model_validate(value).model_dump(
|
|
166
|
+
exclude_none=True
|
|
167
|
+
)
|
|
168
|
+
raise ValueError(
|
|
169
|
+
"slurm_parameters_patch must be a dictionary or SlurmParametersPatch"
|
|
170
|
+
)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from typing import Optional, List
|
|
2
|
+
import urllib.parse
|
|
3
|
+
import socket
|
|
4
|
+
import re
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from odmantic import EmbeddedModel, Field, Model
|
|
7
|
+
from pydantic import field_validator, model_serializer
|
|
8
|
+
|
|
9
|
+
from simstack.util.transform_file_name import transform_file_name
|
|
10
|
+
class GitRepo(Model):
|
|
11
|
+
"""
|
|
12
|
+
Represents a Git repository with relevant attributes such as its URL, branch,
|
|
13
|
+
and whether it is a submodule. Ensures that the URL provided is valid.
|
|
14
|
+
|
|
15
|
+
This class is used to model information about a Git repository, including
|
|
16
|
+
its URL, the branch being used, and whether it is included as a submodule
|
|
17
|
+
within another repository. It provides validation for the URL to ensure that
|
|
18
|
+
it is in the correct format.
|
|
19
|
+
|
|
20
|
+
In the user database there is a list of Git repositories for the user
|
|
21
|
+
|
|
22
|
+
:ivar url: The URL of the Git repository.
|
|
23
|
+
:type url: str
|
|
24
|
+
:ivar branch: The branch of the Git repository. Optional.
|
|
25
|
+
:type branch: Optional[str]
|
|
26
|
+
:ivar is_submodule: Indicates whether the repository is a submodule. Defaults to False.
|
|
27
|
+
:type is_submodule: bool
|
|
28
|
+
"""
|
|
29
|
+
url: str
|
|
30
|
+
branch: Optional[str]
|
|
31
|
+
is_submodule: bool = Field(default=False)
|
|
32
|
+
|
|
33
|
+
@field_validator("url", mode="after")
|
|
34
|
+
@classmethod
|
|
35
|
+
def validate_url(cls, v):
|
|
36
|
+
try:
|
|
37
|
+
result = urllib.parse.urlparse(v)
|
|
38
|
+
if not all([result.scheme, result.netloc]):
|
|
39
|
+
raise ValueError("Invalid URL format")
|
|
40
|
+
except Exception:
|
|
41
|
+
raise ValueError("Invalid URL format")
|
|
42
|
+
return v
|
|
43
|
+
|
|
44
|
+
class ResourceDefinition(Model):
|
|
45
|
+
resource_str: str = Field(unique=True)
|
|
46
|
+
workdir: str # Change Path to str
|
|
47
|
+
hostname: str
|
|
48
|
+
python_paths: List[str] = Field(default_factory=list) # Change List[Path] to List[str]
|
|
49
|
+
environment_start: Optional[str] = None
|
|
50
|
+
ssh_key: Optional[str] = None # Change Optional[Path] to Optional[str]
|
|
51
|
+
routes: Optional[List[str]] = []
|
|
52
|
+
queue: str = "default"
|
|
53
|
+
is_default: bool = False
|
|
54
|
+
git_branch: str = "main"
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def _convert_backslashes(path_str: str) -> str:
|
|
58
|
+
return re.sub(r'\\+', '/', path_str)
|
|
59
|
+
|
|
60
|
+
@field_validator("workdir", mode="before")
|
|
61
|
+
@classmethod
|
|
62
|
+
def convert_workdir(cls, v):
|
|
63
|
+
if isinstance(v, (Path, str)):
|
|
64
|
+
return str(cls._convert_backslashes(str(v)))
|
|
65
|
+
return v
|
|
66
|
+
|
|
67
|
+
@field_validator("python_paths", mode="before")
|
|
68
|
+
@classmethod
|
|
69
|
+
def convert_python_paths(cls, v):
|
|
70
|
+
if isinstance(v, list):
|
|
71
|
+
return [str(cls._convert_backslashes(str(p))) for p in v]
|
|
72
|
+
return v
|
|
73
|
+
|
|
74
|
+
@field_validator("ssh_key", mode="before")
|
|
75
|
+
@classmethod
|
|
76
|
+
def convert_ssh_key(cls, v):
|
|
77
|
+
if v is None:
|
|
78
|
+
return None
|
|
79
|
+
return str(cls._convert_backslashes(str(v)))
|
|
80
|
+
|
|
81
|
+
@field_validator("queue", mode="before")
|
|
82
|
+
@classmethod
|
|
83
|
+
def normalize_queue(cls, v):
|
|
84
|
+
if v is None:
|
|
85
|
+
return "default"
|
|
86
|
+
normalized = str(v).strip()
|
|
87
|
+
return normalized or "default"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def validate_hostname(self):
|
|
91
|
+
current_hostname = socket.gethostname()
|
|
92
|
+
if self.hostname != current_hostname:
|
|
93
|
+
raise ValueError(f"Hostname must match current host. Expected: {current_hostname}, got: {self.hostname}")
|
|
94
|
+
|
|
95
|
+
def validate_ssh_key(self):
|
|
96
|
+
if self.ssh_key is not None:
|
|
97
|
+
file_path = transform_file_name(Path(self.ssh_key)) # Convert to Path for utility
|
|
98
|
+
if not file_path:
|
|
99
|
+
raise ValueError(f"SSH key path does not exist: {self.ssh_key}")
|
|
100
|
+
|
|
101
|
+
def get_ssh_key_path(self):
|
|
102
|
+
if self.ssh_key is not None:
|
|
103
|
+
return transform_file_name(Path(self.ssh_key))
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
def validate_python_path(self):
|
|
107
|
+
for path_str in self.python_paths:
|
|
108
|
+
path = Path(path_str)
|
|
109
|
+
real_path = transform_file_name(path)
|
|
110
|
+
if not path.exists():
|
|
111
|
+
raise ValueError(f"Python path does not exist: {path}")
|
|
112
|
+
if not path.is_dir():
|
|
113
|
+
raise ValueError(f"Python path is not a directory: {path}")
|
|
114
|
+
|
|
115
|
+
def get_python_path(self):
|
|
116
|
+
if self.python_paths:
|
|
117
|
+
return [transform_file_name(Path(p)) for p in self.python_paths]
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
def __repr__(self):
|
|
121
|
+
return f"ResourceDefinition(name={self.resource_str})"
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def from_resource_definition(cls, resource_definition: dict):
|
|
125
|
+
return cls(**resource_definition)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Optional, List
|
|
4
|
+
|
|
5
|
+
from odmantic import Model, ObjectId, Field
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
|
+
|
|
8
|
+
from simstack.models.parameters import Resource
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RunnerEventEnum(str, Enum):
|
|
12
|
+
SHUTDOWN = "shutdown"
|
|
13
|
+
RUNNER_STARTED = "runner_started"
|
|
14
|
+
NODE_STARTED = "node_started"
|
|
15
|
+
NODE_SUBMIT = "node_submit"
|
|
16
|
+
ALIVE = "alive"
|
|
17
|
+
RESTART = "restart"
|
|
18
|
+
CRONTAB_OK = "crontab_ok"
|
|
19
|
+
CRONTAB_GONE = "crontab_gone"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RunnerType(str, Enum):
|
|
23
|
+
NODE_RUNNER = "node_runner"
|
|
24
|
+
RESOURCE_RUNNER = "resource_runner"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RunnerEvent(Model):
|
|
28
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
29
|
+
|
|
30
|
+
timestamp: datetime = Field(default_factory=datetime.now)
|
|
31
|
+
event: RunnerEventEnum
|
|
32
|
+
resource: Resource
|
|
33
|
+
runner_type: RunnerType
|
|
34
|
+
hostname: Optional[str] = None
|
|
35
|
+
user: Optional[str] = None
|
|
36
|
+
pid: Optional[int] = None
|
|
37
|
+
node_id: Optional[ObjectId] = None
|
|
38
|
+
message: Optional[str] = None
|
|
39
|
+
git_status: List[str] = Field(default_factory=list)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Any, Dict, List
|
|
3
|
+
|
|
4
|
+
from odmantic import Model, Field
|
|
5
|
+
from pydantic import field_validator
|
|
6
|
+
|
|
7
|
+
from simstack.models import simstack_model
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SimpleTableColumnType(str, Enum):
|
|
11
|
+
STRING = "string"
|
|
12
|
+
NUMBER = "number"
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def from_value(
|
|
16
|
+
cls, value: "SimpleTableColumnType | str"
|
|
17
|
+
) -> "SimpleTableColumnType":
|
|
18
|
+
if isinstance(value, cls):
|
|
19
|
+
return value
|
|
20
|
+
if not isinstance(value, str):
|
|
21
|
+
raise ValueError(f"Invalid SimpleTable column type: {value!r}")
|
|
22
|
+
|
|
23
|
+
normalized = value.strip()
|
|
24
|
+
try:
|
|
25
|
+
return cls(normalized)
|
|
26
|
+
except ValueError:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
return SIMPLE_TABLE_COLUMN_TYPE_LEGACY_ALIASES[normalized.lower()]
|
|
31
|
+
except KeyError as exc:
|
|
32
|
+
raise ValueError(f"Invalid SimpleTable column type: {value!r}") from exc
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
SIMPLE_TABLE_COLUMN_TYPE_LEGACY_ALIASES = {
|
|
36
|
+
# Existing producers and stored DB documents used these variants before
|
|
37
|
+
# SimpleTable column types were narrowed to logical data types.
|
|
38
|
+
"str": SimpleTableColumnType.STRING,
|
|
39
|
+
"int": SimpleTableColumnType.NUMBER,
|
|
40
|
+
"float": SimpleTableColumnType.NUMBER,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@simstack_model
|
|
45
|
+
class SimpleTable(Model):
|
|
46
|
+
"""
|
|
47
|
+
A simple table model to display tabular data using ag-grid
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
name: str = Field(default="SimpleTable")
|
|
51
|
+
heading: List[str] = Field(default_factory=list)
|
|
52
|
+
row: List[Dict[str, Any]] = Field(default_factory=list)
|
|
53
|
+
type: List[SimpleTableColumnType] = Field(default_factory=list)
|
|
54
|
+
|
|
55
|
+
@field_validator("type", mode="before")
|
|
56
|
+
@classmethod
|
|
57
|
+
def normalize_column_types(cls, value: Any) -> Any:
|
|
58
|
+
if value is None:
|
|
59
|
+
return value
|
|
60
|
+
if isinstance(value, list):
|
|
61
|
+
return [SimpleTableColumnType.from_value(item) for item in value]
|
|
62
|
+
return value
|
|
63
|
+
|
|
64
|
+
def add_column(
|
|
65
|
+
self, column_name: str, column_type: SimpleTableColumnType | str
|
|
66
|
+
) -> None:
|
|
67
|
+
if column_name not in self.heading:
|
|
68
|
+
self.heading.append(column_name)
|
|
69
|
+
self.type.append(SimpleTableColumnType.from_value(column_type))
|
|
70
|
+
|
|
71
|
+
def add_row(self, row: Dict[str, Any]) -> None:
|
|
72
|
+
self.row.append(row)
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def ui_schema(cls) -> Dict[str, str]:
|
|
76
|
+
ui_schema = {
|
|
77
|
+
"ui:field": "SimpleTableField",
|
|
78
|
+
}
|
|
79
|
+
return ui_schema
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import TypeVar, Type, Any, get_type_hints, overload
|
|
3
|
+
|
|
4
|
+
from simstack.util.cleaned_json_schema import cleaned_json_schema
|
|
5
|
+
from simstack.util.custom_model_dump import custom_model_dump
|
|
6
|
+
from simstack.util.default_from_dict import default_from_dict, default_from_model
|
|
7
|
+
from simstack.util.generate_ui_schema import generate_ui_schema
|
|
8
|
+
from simstack.util.ui_tools import ui_make_title
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@overload
|
|
14
|
+
def simstack_model(cls: Type[T]) -> Type[T]:
|
|
15
|
+
...
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def simstack_model(cls: T) -> T:
|
|
19
|
+
"""
|
|
20
|
+
Decorates a given class to equip it with default implementations of utility
|
|
21
|
+
methods for handling operations such as dictionary conversion, schema
|
|
22
|
+
generation, and UI schema generation.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Function to create a properly typed wrapper that preserves docstrings
|
|
26
|
+
def create_typed_wrapper(func, first_param_name="this_class"):
|
|
27
|
+
# Get original type hints
|
|
28
|
+
original_hints = get_type_hints(func)
|
|
29
|
+
|
|
30
|
+
# Create a wrapper with the correct parameters
|
|
31
|
+
@wraps(func) # This preserves metadata like docstrings
|
|
32
|
+
def wrapper(*args, **kwargs):
|
|
33
|
+
return func(*args, **kwargs)
|
|
34
|
+
|
|
35
|
+
# Add explicit docstring if not preserved by wraps
|
|
36
|
+
if not wrapper.__doc__ and func.__doc__:
|
|
37
|
+
wrapper.__doc__ = func.__doc__
|
|
38
|
+
|
|
39
|
+
# Copy the original function's annotations
|
|
40
|
+
wrapper.__annotations__ = {
|
|
41
|
+
first_param_name: Type[Any], # the first param is now the class
|
|
42
|
+
**{
|
|
43
|
+
k: v
|
|
44
|
+
for k, v in original_hints.items()
|
|
45
|
+
if k != "return" and k != first_param_name
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Preserve the return annotation if it exists
|
|
50
|
+
if "return" in original_hints:
|
|
51
|
+
wrapper.__annotations__["return"] = original_hints["return"]
|
|
52
|
+
|
|
53
|
+
return wrapper
|
|
54
|
+
|
|
55
|
+
# Create typed wrappers for all functions with explicit docstrings
|
|
56
|
+
default_class_methods = {
|
|
57
|
+
"json_schema": create_typed_wrapper(cleaned_json_schema),
|
|
58
|
+
"ui_schema": create_typed_wrapper(generate_ui_schema),
|
|
59
|
+
"ui_make_title": create_typed_wrapper(ui_make_title),
|
|
60
|
+
"from_dict": create_typed_wrapper(default_from_dict),
|
|
61
|
+
"from_model": create_typed_wrapper(default_from_model),
|
|
62
|
+
#'make_column_defs': create_typed_wrapper(make_column_defs_helper),
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Add methods only if they don't exist
|
|
66
|
+
for method_name, default_implementation in default_class_methods.items():
|
|
67
|
+
if not hasattr(cls, method_name):
|
|
68
|
+
setattr(cls, method_name, classmethod(default_implementation))
|
|
69
|
+
|
|
70
|
+
default_methods = {
|
|
71
|
+
"custom_model_dump": custom_model_dump,
|
|
72
|
+
#'make_table_entries': make_table_entries_helper
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# Add methods only if they don't exist
|
|
76
|
+
for method_name, default_implementation in default_methods.items():
|
|
77
|
+
if not hasattr(cls, method_name):
|
|
78
|
+
setattr(cls, method_name, default_implementation)
|
|
79
|
+
|
|
80
|
+
# Add a marker attribute to identify decorated classes
|
|
81
|
+
setattr(cls, "_is_simstack_model", True)
|
|
82
|
+
|
|
83
|
+
# Return the original class without casting - the overload handles the typing
|
|
84
|
+
return cls
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def is_simstack_model(cls: Type) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Check if a class has been decorated with @simstack_model.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
cls: The class to check
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
bool: True if the class was decorated with @simstack_model, False otherwise
|
|
96
|
+
"""
|
|
97
|
+
return getattr(cls, "_is_simstack_model", False)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from odmantic import Model, ObjectId
|
|
4
|
+
|
|
5
|
+
from simstack.models.parameters import Resource
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SlurmInfo(Model):
|
|
9
|
+
node_registry: ObjectId
|
|
10
|
+
updated: datetime.datetime
|
|
11
|
+
resource: Resource
|
|
12
|
+
job_id: str
|
|
13
|
+
name: str
|
|
14
|
+
user: str
|
|
15
|
+
code: str
|
|
16
|
+
time: str
|
|
17
|
+
nodes: list[str]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import List, Optional, Dict, Any
|
|
2
|
+
|
|
3
|
+
from odmantic import EmbeddedModel, Field, Model, ObjectId
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AGGridColumnDef(EmbeddedModel):
|
|
7
|
+
"""AG-Grid column definition with support for nested tables."""
|
|
8
|
+
|
|
9
|
+
# Core properties
|
|
10
|
+
field: str = Field(..., description="The field name in the row data to bind to")
|
|
11
|
+
headerName: str = Field(..., description="Display name for the column header")
|
|
12
|
+
|
|
13
|
+
# Sizing properties
|
|
14
|
+
width: Optional[int] = Field(default=None, description="Column width in pixels")
|
|
15
|
+
minWidth: Optional[int] = Field(
|
|
16
|
+
default=None, description="Minimum column width in pixels"
|
|
17
|
+
)
|
|
18
|
+
maxWidth: Optional[int] = Field(
|
|
19
|
+
default=None, description="Maximum column width in pixels"
|
|
20
|
+
)
|
|
21
|
+
flex: Optional[int] = Field(
|
|
22
|
+
default=None, description="Flex sizing for responsive columns"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Display and interaction properties
|
|
26
|
+
hide: Optional[bool] = Field(default=None, description="Whether to hide the column")
|
|
27
|
+
# pinned: Optional[Literal["left", "right"]] = Field(default=None, description="Pin column to left or right")
|
|
28
|
+
sortable: Optional[bool] = Field(
|
|
29
|
+
default=None, description="Whether the column can be sorted"
|
|
30
|
+
)
|
|
31
|
+
resizable: Optional[bool] = Field(
|
|
32
|
+
default=None, description="Whether the column can be resized"
|
|
33
|
+
)
|
|
34
|
+
editable: Optional[bool] = Field(
|
|
35
|
+
default=None, description="Whether cells in this column are editable"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# # Filtering and rendering
|
|
39
|
+
# filter: Optional[Union[bool, str]] = Field(default=None, description="Filter type")
|
|
40
|
+
# cellRenderer: Optional[str] = Field(default=None, description="Custom cell renderer component")
|
|
41
|
+
# cellRendererParams: Optional[Dict[str, Any]] = Field(default=None, description="Parameters for cell renderer")
|
|
42
|
+
|
|
43
|
+
# # Master-Detail specific properties for nested tables
|
|
44
|
+
# cellRendererSelector: Optional[Dict[str, Any]] = Field(default=None, description="Function to select cell renderer based on data")
|
|
45
|
+
#
|
|
46
|
+
# # Nested table configuration
|
|
47
|
+
# is_nested_table: Optional[bool] = Field(default=False, description="Whether this column contains nested table data")
|
|
48
|
+
# nested_table_config: Optional[Dict[str, Any]] = Field(default=None, description="Configuration for nested table rendering")
|
|
49
|
+
#
|
|
50
|
+
# # Row grouping and detail rows
|
|
51
|
+
# rowGroup: Optional[bool] = Field(default=None, description="Whether this column is used for row grouping")
|
|
52
|
+
# showRowGroup: Optional[Union[bool, str]] = Field(default=None, description="Show row group column")
|
|
53
|
+
#
|
|
54
|
+
# # Additional properties
|
|
55
|
+
# custom_properties: Optional[Dict[str, Any]] = Field(default_factory=dict, description="Additional custom properties")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TableArtifactModel(Model):
|
|
59
|
+
parent_id: ObjectId = Field(default=None, description="ID of the node registry")
|
|
60
|
+
columns_defs: List[AGGridColumnDef] = Field(
|
|
61
|
+
default_factory=list, description="AG-Grid column definitions"
|
|
62
|
+
)
|
|
63
|
+
row_data: List[Dict[str, Any]] = Field(
|
|
64
|
+
default_factory=list, description="List of row objects"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Master-Detail configuration
|
|
68
|
+
master_detail: Optional[bool] = Field(
|
|
69
|
+
default=False, description="Enable master-detail rows"
|
|
70
|
+
)
|
|
71
|
+
detail_cell_renderer: Optional[str] = Field(
|
|
72
|
+
default=None, description="Detail panel cell renderer"
|
|
73
|
+
)
|
|
74
|
+
detail_cell_renderer_params: Optional[Dict[str, Any]] = Field(
|
|
75
|
+
default=None, description="Parameters for detail renderer"
|
|
76
|
+
)
|
|
77
|
+
# TODO implement nested tables and rendering
|
|
78
|
+
# # Nested tables storage - simplified to avoid recursion
|
|
79
|
+
# nested_tables: Optional[Dict[str, str]] = Field(default_factory=dict, description="Nested table IDs by reference key")
|
|
80
|
+
#
|
|
81
|
+
# # Tree data configuration
|
|
82
|
+
# tree_data: Optional[bool] = Field(default=False, description="Enable tree data structure")
|
|
83
|
+
# get_data_path: Optional[str] = Field(default=None, description="Function to get data path for tree structure")
|
|
84
|
+
#
|
|
85
|
+
# # Row grouping
|
|
86
|
+
# auto_group_column_def: Optional[AGGridColumnDef] = Field(default=None, description="Auto group column definition")
|
|
87
|
+
# group_default_expanded: Optional[int] = Field(default=None, description="Default expansion level for groups")
|
simstack/models/tag.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# this file makes sure that find_root keeps searching
|
|
Binary file
|