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
|
File without changes
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from odmantic.exceptions import DocumentParsingError
|
|
7
|
+
from pydantic import ValidationError
|
|
8
|
+
|
|
9
|
+
from simstack.core.context import context
|
|
10
|
+
from simstack.models.models import ModelMapping
|
|
11
|
+
from simstack.models.simstack_model import is_simstack_model
|
|
12
|
+
from simstack.util.db import Database
|
|
13
|
+
from simstack.util.path_manager import path_manager
|
|
14
|
+
from simstack.tables.table_builder import TableBuilderBase
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger("ModelTable")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CreateModelTable(TableBuilderBase):
|
|
20
|
+
"""
|
|
21
|
+
Helper class to build the model table without passing around many parameters.
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
creator = CreateModelTable(db)
|
|
25
|
+
await creator.make_model_table()
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def logger(self) -> logging.Logger:
|
|
30
|
+
return logger
|
|
31
|
+
|
|
32
|
+
async def build(self, *args, **kwargs) -> None:
|
|
33
|
+
await super().build(*args, **kwargs)
|
|
34
|
+
await context.refresh_mappings(models=True, nodes=False)
|
|
35
|
+
|
|
36
|
+
async def _process_module(self, module, drops: str) -> None:
|
|
37
|
+
await self._create_models_from_module(module, drops)
|
|
38
|
+
|
|
39
|
+
async def _create_models_from_module(self, module, drops: str):
|
|
40
|
+
"""Create ModelMapping entries for all relevant classes in a module."""
|
|
41
|
+
classes = inspect.getmembers(module, inspect.isclass)
|
|
42
|
+
|
|
43
|
+
for class_name, new_class in classes:
|
|
44
|
+
# this is required because of the Odmantic Metaclass Model
|
|
45
|
+
# subclass does not work even if applied to the imported classes
|
|
46
|
+
# this is a bug in importlib
|
|
47
|
+
bases = [base.__name__ for base in new_class.__bases__]
|
|
48
|
+
is_ui_model = any("UIModel" in s for s in bases) or is_simstack_model(
|
|
49
|
+
new_class
|
|
50
|
+
)
|
|
51
|
+
is_model = any(s == "Model" for s in bases)
|
|
52
|
+
|
|
53
|
+
is_embedded_model = any(s == "EmbeddedModel" for s in bases)
|
|
54
|
+
|
|
55
|
+
if not (is_model or is_ui_model or is_embedded_model):
|
|
56
|
+
continue
|
|
57
|
+
if class_name == "Model":
|
|
58
|
+
continue
|
|
59
|
+
if new_class.__module__ != module.__name__:
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
new_modules = new_class.__module__.split(".")
|
|
63
|
+
# Use drops from the path_info dictionary
|
|
64
|
+
if drops != "":
|
|
65
|
+
drop_modules = drops.split(".")
|
|
66
|
+
while (
|
|
67
|
+
new_modules and drop_modules and new_modules[0] == drop_modules[0]
|
|
68
|
+
):
|
|
69
|
+
new_modules.pop(0)
|
|
70
|
+
drop_modules.pop(0)
|
|
71
|
+
# if len(drop_modules) > 0:
|
|
72
|
+
# raise ValueError(
|
|
73
|
+
# "drop modules not empty: ", drop_modules, new_class.__module__
|
|
74
|
+
# )
|
|
75
|
+
full_mapping = ".".join(new_modules) + "." + class_name
|
|
76
|
+
logger.debug(f" Class: {class_name} Model Mapping: {full_mapping}")
|
|
77
|
+
|
|
78
|
+
# Remove any existing ModelMapping entry for this class
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
existing_entries = await self.db.find(
|
|
82
|
+
ModelMapping, ModelMapping.name == class_name
|
|
83
|
+
)
|
|
84
|
+
except (ValidationError, NameError, DocumentParsingError) as e:
|
|
85
|
+
logger.error(
|
|
86
|
+
f"Error finding existing ModelMapping for {class_name}: {e}"
|
|
87
|
+
)
|
|
88
|
+
existing_entries = []
|
|
89
|
+
|
|
90
|
+
if len(existing_entries) > 1:
|
|
91
|
+
error_msg = f"Fatal error: Found {len(existing_entries)} ModelMapping entries for class_name '{class_name}'. Expected at most one."
|
|
92
|
+
logger.fatal(error_msg)
|
|
93
|
+
raise RuntimeError(error_msg)
|
|
94
|
+
|
|
95
|
+
if len(existing_entries) == 1:
|
|
96
|
+
existing_mapping = existing_entries[0].mapping
|
|
97
|
+
if existing_mapping != full_mapping:
|
|
98
|
+
logger.warning(
|
|
99
|
+
f"Replacing ModelMapping entry for {class_name}: "
|
|
100
|
+
f"old mapping '{existing_mapping}' -> new mapping '{full_mapping}'"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
await self.db.delete(existing_entries[0])
|
|
104
|
+
logger.debug(f"Deleted ModelMapping entry for {class_name}")
|
|
105
|
+
|
|
106
|
+
# EmbeddedModels have no collection by may be simstack_models. They are never saved/retrieved
|
|
107
|
+
collection_name = getattr(new_class, "__collection__", None)
|
|
108
|
+
if collection_name is None:
|
|
109
|
+
if is_embedded_model:
|
|
110
|
+
collection_name = "EmbeddedModel"
|
|
111
|
+
else:
|
|
112
|
+
logger.error(f"No collection specified for {class_name}")
|
|
113
|
+
|
|
114
|
+
# Create the new ModelMapping entry (pickle functionality removed)
|
|
115
|
+
if is_ui_model:
|
|
116
|
+
model_entry = ModelMapping(
|
|
117
|
+
name=class_name,
|
|
118
|
+
mapping=full_mapping,
|
|
119
|
+
collection_name=collection_name,
|
|
120
|
+
json_schema=json.dumps(new_class.json_schema()),
|
|
121
|
+
ui_schema=json.dumps(new_class.ui_schema()),
|
|
122
|
+
route="",
|
|
123
|
+
)
|
|
124
|
+
logger.debug(
|
|
125
|
+
f"SimStack Model: {class_name} Mapping: {full_mapping} Collection: {collection_name}"
|
|
126
|
+
)
|
|
127
|
+
# open a file in a subdirectory of the current file schema/model.json
|
|
128
|
+
if self.write_schema:
|
|
129
|
+
project_root = self.project_root
|
|
130
|
+
json_file_dir = project_root / "schema"
|
|
131
|
+
json_file_dir.mkdir(parents=True, exist_ok=True)
|
|
132
|
+
|
|
133
|
+
combined_schema = {
|
|
134
|
+
"json_schema": new_class.json_schema(),
|
|
135
|
+
"ui_schema": new_class.ui_schema(),
|
|
136
|
+
}
|
|
137
|
+
with open(json_file_dir / f"{class_name}.json", "w") as f:
|
|
138
|
+
f.write(json.dumps(combined_schema, indent=4))
|
|
139
|
+
else:
|
|
140
|
+
model_entry = ModelMapping(
|
|
141
|
+
name=class_name,
|
|
142
|
+
mapping=full_mapping,
|
|
143
|
+
collection_name=collection_name,
|
|
144
|
+
)
|
|
145
|
+
logger.debug(
|
|
146
|
+
f"Model: {class_name} Mapping: {full_mapping} Collection: {collection_name}"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
await self.db.save(model_entry)
|
|
150
|
+
|
|
151
|
+
async def _make_models_for_path(self, path_name: str):
|
|
152
|
+
"""Build model mappings for all Python files under a configured path."""
|
|
153
|
+
path_info = path_manager.get_path(path_name)
|
|
154
|
+
path = path_info["path"]
|
|
155
|
+
drops = path_info.get("drops", "")
|
|
156
|
+
logger.info(f"Making model_table entries for files in {path}")
|
|
157
|
+
|
|
158
|
+
# Process each file in this path
|
|
159
|
+
for file_path in path_manager.find_python_files(path_name):
|
|
160
|
+
await self._create_model_models_from_file(file_path, drops)
|
|
161
|
+
|
|
162
|
+
async def clear_table(self) -> None:
|
|
163
|
+
self.logger.info("Clearing ModelMapping collection")
|
|
164
|
+
await self.db.get_collection(ModelMapping).drop()
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# Public API preserved for existing callers (e.g. tests)
|
|
168
|
+
async def make_model_table(
|
|
169
|
+
db : Database,
|
|
170
|
+
dirs: list[str] = None,
|
|
171
|
+
drops: str = "",
|
|
172
|
+
write_schema: bool = False,
|
|
173
|
+
clear: bool = False,
|
|
174
|
+
project_root: Path = None,
|
|
175
|
+
ignore_entrypoints: bool = False,
|
|
176
|
+
):
|
|
177
|
+
"""
|
|
178
|
+
Rebuild the model table using the given database.
|
|
179
|
+
|
|
180
|
+
This is a thin wrapper around CreateModelTable for backward compatibility.
|
|
181
|
+
"""
|
|
182
|
+
creator = CreateModelTable(db, write_schema=write_schema, project_root=project_root)
|
|
183
|
+
await creator.build(dirs=dirs, drops=drops, clear=clear, ignore_entrypoints=ignore_entrypoints)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def create_model_table_main():
|
|
187
|
+
TableBuilderBase.cli_main(CreateModelTable)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if __name__ == "__main__":
|
|
191
|
+
create_model_table_main()
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import importlib
|
|
3
|
+
import inspect
|
|
4
|
+
import os
|
|
5
|
+
from typing import Optional, Callable, List, Dict
|
|
6
|
+
from simstack.models import NodeModel
|
|
7
|
+
from simstack.util.importer import import_function
|
|
8
|
+
from simstack.util.docstring_parser import DocstringParser
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
logger = logging.getLogger("node_children")
|
|
12
|
+
|
|
13
|
+
def _import_callable_from_mapping(function_mapping: str) -> Optional[Callable]:
|
|
14
|
+
"""
|
|
15
|
+
Import a callable from a 'module.submodule.func' mapping string.
|
|
16
|
+
"""
|
|
17
|
+
try:
|
|
18
|
+
module_path, _, attr = function_mapping.rpartition(".")
|
|
19
|
+
if not module_path or not attr:
|
|
20
|
+
logger.warning(f"Invalid function_mapping '{function_mapping}' (expected 'module.func').")
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
module = importlib.import_module(module_path)
|
|
24
|
+
obj = getattr(module, attr, None)
|
|
25
|
+
if obj is None or not callable(obj):
|
|
26
|
+
logger.warning(f"Could not resolve callable for '{function_mapping}'.")
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
return obj
|
|
30
|
+
except Exception as e:
|
|
31
|
+
logger.warning(f"Could not import '{function_mapping}': {e}")
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
def _extract_called_functions(func: Callable) -> List[str]:
|
|
35
|
+
"""
|
|
36
|
+
Inspect the function code and return all the function calls made within it.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
List of function names called within the function.
|
|
40
|
+
"""
|
|
41
|
+
called_functions: List[str] = []
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
source = inspect.getsource(func)
|
|
45
|
+
tree = ast.parse(source)
|
|
46
|
+
|
|
47
|
+
task_creators = {"create_tasks", "ensure_future"}
|
|
48
|
+
|
|
49
|
+
for node in ast.walk(tree):
|
|
50
|
+
if isinstance(node, ast.Call):
|
|
51
|
+
if isinstance(node.func, ast.Name):
|
|
52
|
+
# Direct function call: func_name()
|
|
53
|
+
called_functions.append(node.func.id)
|
|
54
|
+
elif isinstance(node.func, ast.Attribute):
|
|
55
|
+
# Attribute function call: obj.method()
|
|
56
|
+
if isinstance(node.func.value, ast.Name):
|
|
57
|
+
called_functions.append(f"{node.func.value.id}.{node.func.attr}")
|
|
58
|
+
else:
|
|
59
|
+
called_functions.append(node.func.attr)
|
|
60
|
+
|
|
61
|
+
# Detect async task creation: create_tasks(func()), ensure_future(func()), etc.
|
|
62
|
+
if isinstance(node.func, ast.Name) and node.func.id in task_creators:
|
|
63
|
+
if node.args and isinstance(node.args[0], ast.Call):
|
|
64
|
+
task_call = node.args[0]
|
|
65
|
+
if isinstance(task_call.func, ast.Name):
|
|
66
|
+
called_functions.append(task_call.func.id)
|
|
67
|
+
elif isinstance(task_call.func, ast.Attribute):
|
|
68
|
+
if isinstance(task_call.func.value, ast.Name):
|
|
69
|
+
called_functions.append(f"{task_call.func.value.id}.{task_call.func.attr}")
|
|
70
|
+
else:
|
|
71
|
+
called_functions.append(task_call.func.attr)
|
|
72
|
+
|
|
73
|
+
elif isinstance(node.func, ast.Attribute) and node.func.attr in task_creators:
|
|
74
|
+
if node.args and isinstance(node.args[0], ast.Call):
|
|
75
|
+
task_call = node.args[0]
|
|
76
|
+
if isinstance(task_call.func, ast.Name):
|
|
77
|
+
called_functions.append(task_call.func.id)
|
|
78
|
+
elif isinstance(task_call.func, ast.Attribute):
|
|
79
|
+
if isinstance(task_call.func.value, ast.Name):
|
|
80
|
+
called_functions.append(f"{task_call.func.value.id}.{task_call.func.attr}")
|
|
81
|
+
else:
|
|
82
|
+
called_functions.append(task_call.func.attr)
|
|
83
|
+
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logger.warning(f"Could not extract called functions from {getattr(func, '__name__', '<unknown>')}: {e}")
|
|
86
|
+
|
|
87
|
+
return called_functions
|
|
88
|
+
|
|
89
|
+
def normalize_text(s: str) -> str:
|
|
90
|
+
return s.encode("utf-8", errors="replace").decode("utf-8")
|
|
91
|
+
|
|
92
|
+
async def update_node_children(database, drops: str) -> None:
|
|
93
|
+
"""
|
|
94
|
+
1) Read all registered nodes from NodeModel.
|
|
95
|
+
2) For each node, import its function and extract called functions.
|
|
96
|
+
3) Keep only those calls that correspond to nodes in the table.
|
|
97
|
+
4) Update the NodeModel.called_nodes of the original function with a list of *function_mapping* strings.
|
|
98
|
+
"""
|
|
99
|
+
node_models: List[NodeModel] = await database.find(NodeModel)
|
|
100
|
+
|
|
101
|
+
# Build lookup tables to resolve extracted names -> NodeModel.function_mapping
|
|
102
|
+
mapping_by_node_name: Dict[str, str] = { nm.name: nm.function_mapping for nm in node_models}
|
|
103
|
+
mapping_set: set[str] = set(nm.function_mapping for nm in node_models)
|
|
104
|
+
|
|
105
|
+
for nm in node_models:
|
|
106
|
+
func = await import_function(nm.function_mapping, database, None, True)
|
|
107
|
+
if func is None:
|
|
108
|
+
continue
|
|
109
|
+
|
|
110
|
+
parser = DocstringParser(inspect.getdoc(func))
|
|
111
|
+
|
|
112
|
+
called = _extract_called_functions(func)
|
|
113
|
+
logger.debug(f"Node {nm.name} called: {called}")
|
|
114
|
+
called_from_docstring = parser.called_nodes()
|
|
115
|
+
resolved: set[str] = set()
|
|
116
|
+
for called_name in called:
|
|
117
|
+
# If the extractor ever returns a full mapping, accept it directly
|
|
118
|
+
if called_name in mapping_set:
|
|
119
|
+
resolved.add(called_name)
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
# If it matches a node name, resolve via node name
|
|
123
|
+
if called_name in mapping_by_node_name:
|
|
124
|
+
resolved.add(mapping_by_node_name[called_name])
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
# Otherwise, resolve by last segment (handles "obj.method" and "module.func")
|
|
128
|
+
short = called_name.split(".")[-1]
|
|
129
|
+
if short in mapping_by_node_name:
|
|
130
|
+
resolved.add(mapping_by_node_name[short])
|
|
131
|
+
if called_from_docstring is not None and short in called_from_docstring:
|
|
132
|
+
del called_from_docstring[short]
|
|
133
|
+
continue
|
|
134
|
+
|
|
135
|
+
# go over the leftovers in the docstring
|
|
136
|
+
if called_from_docstring is not None:
|
|
137
|
+
for called_name in called_from_docstring:
|
|
138
|
+
if called_name in mapping_set:
|
|
139
|
+
resolved.add(called_name)
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# If it matches a node name, resolve via node name
|
|
143
|
+
if called_name in mapping_by_node_name:
|
|
144
|
+
resolved.add(mapping_by_node_name[called_name])
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
# Otherwise, resolve by last segment (handles "obj.method" and "module.func")
|
|
148
|
+
# short = called_name.split(".")[-1]
|
|
149
|
+
# if short in mapping_by_node_name:
|
|
150
|
+
# resolved.add(mapping_by_short_name[short])
|
|
151
|
+
# continue
|
|
152
|
+
|
|
153
|
+
if len(resolved) != 0:
|
|
154
|
+
logger.debug(f"Resolved children of {nm.name} to {resolved}")
|
|
155
|
+
nm.called_nodes = sorted(resolved)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
await database.get_collection(NodeModel).update_one(
|
|
159
|
+
{"_id": nm.id},
|
|
160
|
+
{"$set": {"called_nodes": nm.called_nodes}},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
with open("node_models.txt", "w") as outfile:
|
|
164
|
+
for nm in node_models:
|
|
165
|
+
mapping_set.add(nm.function_mapping)
|
|
166
|
+
mapping_by_node_name[nm.name] = nm.function_mapping
|
|
167
|
+
|
|
168
|
+
# Write formatted NodeModel information
|
|
169
|
+
outfile.write(f"{'=' * 80}\n")
|
|
170
|
+
|
|
171
|
+
outfile.write(f"Node: {nm.name if nm.name else 'WARNING: Missing name'}\n")
|
|
172
|
+
outfile.write(
|
|
173
|
+
f"Function Mapping: {nm.function_mapping if nm.function_mapping else 'WARNING: Missing function_mapping'}\n")
|
|
174
|
+
|
|
175
|
+
if hasattr(nm, 'description') and nm.description:
|
|
176
|
+
try:
|
|
177
|
+
cleaned_description = normalize_text(nm.description)
|
|
178
|
+
outfile.write(f"Description: {cleaned_description}\n")
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.warning(f"Could not normalize description for {nm.name}: {e}")
|
|
181
|
+
else:
|
|
182
|
+
|
|
183
|
+
outfile.write(f"Description: WARNING: Missing description\n")
|
|
184
|
+
|
|
185
|
+
# Write input_mappings in table format
|
|
186
|
+
outfile.write(f"\nInput Mappings:\n")
|
|
187
|
+
if hasattr(nm, 'input_mappings') and nm.input_mappings:
|
|
188
|
+
outfile.write(f" {'Arg Name':<20} | {'Model':<50} | {'Field':<20}\n")
|
|
189
|
+
outfile.write(f" {'-' * 20}-+-{'-' * 50}-+-{'-' * 20}\n")
|
|
190
|
+
for mapping in nm.input_mappings:
|
|
191
|
+
arg_name = getattr(mapping, 'name', 'N/A')
|
|
192
|
+
model = getattr(mapping, 'mapping', 'N/A')
|
|
193
|
+
field = getattr(mapping, 'description', 'N/A')
|
|
194
|
+
outfile.write(f" {str(arg_name):<20} | {str(model):<50} | {str(field):<20}\n")
|
|
195
|
+
else:
|
|
196
|
+
outfile.write(f" (none)\n")
|
|
197
|
+
|
|
198
|
+
# Write result_mappings in table format
|
|
199
|
+
outfile.write(f"\nResult Mappings:\n")
|
|
200
|
+
if hasattr(nm, 'result_mappings') and nm.result_mappings:
|
|
201
|
+
outfile.write(f" {'Arg Name':<20} | {'Model':<50} | {'Field':<20}\n")
|
|
202
|
+
outfile.write(f" {'-' * 20}-+-{'-' * 50}-+-{'-' * 20}\n")
|
|
203
|
+
for mapping in nm.result_mappings:
|
|
204
|
+
arg_name = getattr(mapping, 'name', 'N/A')
|
|
205
|
+
model = getattr(mapping, 'mapping', 'N/A')
|
|
206
|
+
field = getattr(mapping, 'description', 'N/A')
|
|
207
|
+
outfile.write(f" {str(arg_name):<20} | {str(model):<50} | {str(field):<20}\n")
|
|
208
|
+
else:
|
|
209
|
+
outfile.write(f" (none)\n")
|
|
210
|
+
|
|
211
|
+
# Write called_nodes (node children)
|
|
212
|
+
outfile.write(f"\nCalled Nodes (Children):\n")
|
|
213
|
+
if hasattr(nm, 'called_nodes') and nm.called_nodes:
|
|
214
|
+
for called_node in nm.called_nodes:
|
|
215
|
+
outfile.write(f" - {called_node}\n")
|
|
216
|
+
else:
|
|
217
|
+
outfile.write(f" (none)\n")
|
|
218
|
+
|
|
219
|
+
outfile.write(f"{'-' * 80}\n\n")
|