deriva-cli 0.8.1__tar.gz → 0.8.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/PKG-INFO +6 -7
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/manager.py +29 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/models.py +28 -14
- deriva_cli-0.8.3/deriva/adapters/archimate/views.py +154 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/xml_export.py +107 -10
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/__init__.py +7 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/data/derivation_config.json +126 -86
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/data/extraction_config.json +106 -4
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/data/file_types.json +8 -0
- deriva_cli-0.8.3/deriva/adapters/database/data/function_models/pcf-8.0-cross-industry.csv +90 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/manager.py +19 -1
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/__init__.py +20 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/manager.py +58 -2
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/models.py +340 -5
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/__init__.py +0 -4
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/manager.py +21 -10
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/model_registry.py +11 -5
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/models.py +4 -0
- deriva_cli-0.8.3/deriva/adapters/llm/retry.py +147 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/schemas.py +34 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/repository/manager.py +5 -20
- deriva_cli-0.8.3/deriva/adapters/treesitter/cdk.py +312 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/__init__.py +1 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/javascript.py +21 -15
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/python.py +16 -15
- deriva_cli-0.8.3/deriva/adapters/treesitter/languages/sql.py +98 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/manager.py +4 -1
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/cli.py +16 -1
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/commands/config.py +56 -17
- deriva_cli-0.8.3/deriva/cli/commands/graph.py +27 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/commands/repo.py +1 -1
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/commands/run.py +10 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/cache_utils.py +201 -36
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/logging.py +6 -63
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/settings.py +4 -3
- deriva_cli-0.8.3/deriva/modules/analysis/conventions.py +302 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/semantic_matching.py +29 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/application_service.py +3 -21
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/base.py +318 -39
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/business_actor.py +3 -21
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/business_object.py +3 -23
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/business_process.py +3 -22
- deriva_cli-0.8.3/deriva/modules/derivation/component_services.py +835 -0
- deriva_cli-0.8.3/deriva/modules/derivation/detail_level.py +85 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/element_base.py +245 -26
- deriva_cli-0.8.3/deriva/modules/derivation/function_model.py +415 -0
- deriva_cli-0.8.3/deriva/modules/derivation/levels.py +224 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/__init__.py +6 -8
- deriva_cli-0.8.3/deriva/modules/derivation/refine/abstraction_levels.py +261 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/base.py +2 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/duplicate_elements.py +27 -107
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/duplicate_relationships.py +18 -38
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/joint.py +111 -45
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/joint_consistency.py +27 -52
- deriva_cli-0.8.3/deriva/modules/extraction/build_modules.py +254 -0
- deriva_cli-0.8.3/deriva/modules/extraction/cooperation.py +242 -0
- deriva_cli-0.8.3/deriva/modules/extraction/data_domains.py +359 -0
- deriva_cli-0.8.3/deriva/modules/extraction/data_entities.py +277 -0
- deriva_cli-0.8.3/deriva/modules/extraction/deployable_units.py +508 -0
- deriva_cli-0.8.3/deriva/modules/extraction/deployments.py +671 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/edges.py +137 -45
- deriva_cli-0.8.3/deriva/modules/extraction/lifecycles.py +395 -0
- deriva_cli-0.8.3/deriva/modules/extraction/roles.py +91 -0
- deriva_cli-0.8.3/deriva/modules/extraction/step_tags.py +139 -0
- deriva_cli-0.8.3/deriva/modules/extraction/technologies.py +63 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/type_definition.py +2 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/__init__.py +3 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/about.py +10 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/config.py +48 -22
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/config_models.py +2 -2
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/derivation.py +568 -63
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/export_bundle.py +5 -0
- deriva_cli-0.8.3/deriva/services/export_levels.py +117 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/extraction.py +1070 -18
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/llm_log.py +2 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/model_configs.py +12 -1
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/session.py +61 -9
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/pyproject.toml +11 -9
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/pyproject.toml.orig +10 -11
- deriva_cli-0.8.1/deriva/adapters/llm/retry.py +0 -421
- deriva_cli-0.8.1/deriva/modules/derivation/component_services.py +0 -265
- deriva_cli-0.8.1/deriva/modules/derivation/refine/circular_relationships.py +0 -251
- deriva_cli-0.8.1/deriva/modules/derivation/refine/relationship_consolidation.py +0 -299
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/LICENSE +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/documentation/Diagram.html +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/documentation/View.html +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/documentation/model.html +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/examples/archimate3_Diagram.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/examples/archimate3_Model.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/examples/archimate3_View.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/schemas/archimate3_Diagram.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/schemas/archimate3_Model.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/schemas/archimate3_View.xsd +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-1.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-10.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-2.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-3.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-4.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-5.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-7.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-8.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/archimate_xsd/snippets/Interoperability testing snippet-9.xml +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/archimate/validation.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/data/derivation_patterns.json +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/data/system_settings.json +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/db_tool.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/scripts/7_extraction_params.sql +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/database/scripts/schema.sql +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/grafeo/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/grafeo/manager.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/cache.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/graph/metamodel.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/cache.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/llm/rate_limiter.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/extract.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/language.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/manager.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/models.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/phrases.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/settings.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/text.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/nlp/translate.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/repository/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/repository/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/repository/models.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/base.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/bms.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/cobol.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/csharp.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/java.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/jcl.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/languages/structural.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/adapters/treesitter/models.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/README.md +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/commands/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/cli/progress.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/chunking.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/document_reader.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/exceptions.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/file_utils.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/json_utils.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/llm_utils.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/naming.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/ocel.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/paths.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/schema_utils.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/time_utils.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/timing.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/common/types.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/consistency.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/cross_repo_analysis.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/deviation.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/fit_analysis.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/model_quality.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/run_consistency.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/stability_analysis.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/analysis/types.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/application_component.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/application_interface.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/business_event.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/business_function.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/data_object.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/device.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/node.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/prep.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/cross_layer.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/graph_relationships.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/normalization.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/orphan_elements.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/refine/structural_consistency.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/system_software.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/derivation/technology_service.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/__init__.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/base.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/business_concept.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/classification.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/concept_candidates.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/directory.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/directory_classification.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/external_dependency.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/file.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/method.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/repository.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/technology_candidates.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/modules/extraction/test.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/ontology.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/overfit.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/pipeline.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/deriva/services/trace.py +0 -0
- {deriva_cli-0.8.1 → deriva_cli-0.8.3}/packages/README-deriva-cli.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deriva-cli
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
4
4
|
Summary: Deriva is a research project aimed at enabling digital architects by automating the derivation of enterprise architecture models. Deriva uses dual knowledge graphs, heuristics and LLM's.
|
|
5
5
|
Keywords: archimate,enterprise-architecture,code-analysis,llm,grafeo,fastapi
|
|
6
6
|
Author: S. T. Grond
|
|
@@ -35,15 +35,14 @@ Requires-Dist: tree-sitter-c-sharp>=0.23
|
|
|
35
35
|
Requires-Dist: pypdf>=6
|
|
36
36
|
Requires-Dist: python-docx>=1.2
|
|
37
37
|
Requires-Dist: spacy==3.8.16
|
|
38
|
-
Requires-Dist: ctranslate2==4.8.
|
|
38
|
+
Requires-Dist: ctranslate2==4.8.3
|
|
39
39
|
Requires-Dist: sentencepiece==0.2.2
|
|
40
40
|
Requires-Dist: solvor>=0.6.3
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
Requires-Dist:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist: structlog>=26.1.0
|
|
41
|
+
Requires-Dist: pydantic-ai-slim[openai,anthropic]>=2.55
|
|
42
|
+
Requires-Dist: httpx2>=2.13
|
|
43
|
+
Requires-Dist: lmdb>=1.6
|
|
45
44
|
Requires-Dist: typer>=0.27
|
|
46
|
-
Requires-Dist:
|
|
45
|
+
Requires-Dist: tree-sitter-typescript==0.23.2
|
|
47
46
|
Requires-Python: >=3.14
|
|
48
47
|
Project-URL: Homepage, https://deriva.dev
|
|
49
48
|
Project-URL: Documentation, https://docs.deriva.dev
|
|
@@ -577,6 +577,35 @@ class ArchimateManager:
|
|
|
577
577
|
key=lambda e: str(e["identifier"]),
|
|
578
578
|
)
|
|
579
579
|
|
|
580
|
+
def update_element_properties(self, updates: dict[str, dict[str, Any]]) -> int:
|
|
581
|
+
"""Merge keys into the properties of elements (identifier -> keys), leaving their other keys; returns how many changed."""
|
|
582
|
+
if self.db is None:
|
|
583
|
+
raise RuntimeError("Not connected to grafeo. Call connect() first.")
|
|
584
|
+
changed = 0
|
|
585
|
+
for identifier, keys in sorted(updates.items()):
|
|
586
|
+
rows = self.db.execute(f"MATCH (e:`{self.namespace}` {{identifier: $identifier}}) RETURN e.properties AS properties", {"identifier": identifier})
|
|
587
|
+
if not rows:
|
|
588
|
+
continue
|
|
589
|
+
merged = {**(rows[0].get("properties") or {}), **keys}
|
|
590
|
+
self.db.execute_write(f"MATCH (e:`{self.namespace}` {{identifier: $identifier}}) SET e.properties = $properties", {"identifier": identifier, "properties": merged})
|
|
591
|
+
changed += 1
|
|
592
|
+
return changed
|
|
593
|
+
|
|
594
|
+
def update_relationship_properties(self, updates: dict[str, dict[str, Any]]) -> int:
|
|
595
|
+
"""Merge keys into the properties of relationships (identifier -> keys), in place; returns how many changed."""
|
|
596
|
+
if self.db is None:
|
|
597
|
+
raise RuntimeError("Not connected to grafeo. Call connect() first.")
|
|
598
|
+
changed = 0
|
|
599
|
+
for identifier, keys in sorted(updates.items()):
|
|
600
|
+
match = f"MATCH (:`{self.namespace}`)-[r {{identifier: $identifier}}]->(:`{self.namespace}`)"
|
|
601
|
+
rows = self.db.execute(f"{match} RETURN r.properties AS properties", {"identifier": identifier})
|
|
602
|
+
if not rows:
|
|
603
|
+
continue
|
|
604
|
+
merged = {**(rows[0].get("properties") or {}), **keys}
|
|
605
|
+
self.db.execute_write(f"{match} SET r.properties = $properties", {"identifier": identifier, "properties": merged})
|
|
606
|
+
changed += 1
|
|
607
|
+
return changed
|
|
608
|
+
|
|
580
609
|
def delete_relationship(self, identifier: str) -> bool:
|
|
581
610
|
"""Delete a relationship by identifier.
|
|
582
611
|
|
|
@@ -122,6 +122,13 @@ ELEMENT_TYPES: dict[str, ElementType] = {
|
|
|
122
122
|
aspect="Behavior",
|
|
123
123
|
description="An explicitly defined exposed technology behavior",
|
|
124
124
|
),
|
|
125
|
+
# A detail-level element (the export's detail level): the deployed image or package of a component
|
|
126
|
+
"Artifact": ElementType(
|
|
127
|
+
name="Artifact",
|
|
128
|
+
layer="Technology",
|
|
129
|
+
aspect="Passive",
|
|
130
|
+
description="A piece of data that is used or produced in a software development process, or by deployment and operation of an IT system",
|
|
131
|
+
),
|
|
125
132
|
}
|
|
126
133
|
|
|
127
134
|
|
|
@@ -152,6 +159,7 @@ BEHAVIOR_ELEMENTS: set[str] = {
|
|
|
152
159
|
PASSIVE_ELEMENTS: set[str] = {
|
|
153
160
|
"DataObject",
|
|
154
161
|
"BusinessObject",
|
|
162
|
+
"Artifact",
|
|
155
163
|
}
|
|
156
164
|
|
|
157
165
|
# All elements
|
|
@@ -178,6 +186,7 @@ TECHNOLOGY_LAYER: set[str] = {
|
|
|
178
186
|
"Device",
|
|
179
187
|
"SystemSoftware",
|
|
180
188
|
"TechnologyService",
|
|
189
|
+
"Artifact",
|
|
181
190
|
}
|
|
182
191
|
|
|
183
192
|
|
|
@@ -196,7 +205,7 @@ def layer_of(element_type: str) -> str:
|
|
|
196
205
|
# ArchiMate 3.2 Relationship Table
|
|
197
206
|
# =============================================================================
|
|
198
207
|
# Source: ArchiMate 3.2 Specification, Appendix B.5 "Relationship Tables", restricted
|
|
199
|
-
# to the 13 element types Deriva derives. The spec publishes the tables as images;
|
|
208
|
+
# to the 13 element types Deriva derives plus Artifact (the export's detail level). The spec publishes the tables as images;
|
|
200
209
|
# letters were read from them and cross-checked (case-insensitively, all 169 cells)
|
|
201
210
|
# against Archi's relationships.xml v3.2.
|
|
202
211
|
#
|
|
@@ -233,24 +242,29 @@ _TABLE_COLUMNS = (
|
|
|
233
242
|
"Device",
|
|
234
243
|
"SystemSoftware",
|
|
235
244
|
"TechnologyService",
|
|
245
|
+
"Artifact",
|
|
236
246
|
)
|
|
237
247
|
|
|
248
|
+
# Artifact (row and column) from Archi's relationships.xml; uppercase where the spec's metamodel figures show the
|
|
249
|
+
# relationship: Node, Device and SystemSoftware are assigned to an artifact, an artifact realizes an application
|
|
250
|
+
# component, a data object or system software; artifacts compose, aggregate and specialize artifacts.
|
|
238
251
|
# Row = source, columns in _TABLE_COLUMNS order = target.
|
|
239
252
|
# fmt: off
|
|
240
253
|
_TABLE_ROWS: dict[str, tuple[str, ...]] = {
|
|
241
|
-
"BusinessActor": ("SCGvtfO", "IvtfO", "IvtfO", "IvtfO", "aO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO"),
|
|
242
|
-
"BusinessProcess": ("vtfO", "SCGvTFO", "CGvTFO", "vTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO"),
|
|
243
|
-
"BusinessFunction": ("vtfO", "CGvTFO", "SCGvTFO", "vTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO"),
|
|
244
|
-
"BusinessEvent": ("vtfO", "vTFO", "vTFO", "SCGvTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO"),
|
|
245
|
-
"BusinessObject": ("O", "O", "O", "O", "SCGO", "O", "O", "O", "O", "O", "O", "O", "O"),
|
|
246
|
-
"ApplicationComponent": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "SCGRvtfO", "CgrvtfO", "irvtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO"),
|
|
247
|
-
"ApplicationInterface": ("VtfO", "vtfO", "vtfO", "vtfO", "aO", "VtfO", "SCGvtfO", "IvtfO", "aO", "VtfO", "VtfO", "VtfO", "vtfO"),
|
|
248
|
-
"ApplicationService": ("VtfO", "VtfO", "VtfO", "vtfO", "aO", "VtfO", "vtfO", "SCGvTFO", "AO", "VtfO", "VtfO", "VtfO", "vtfO"),
|
|
249
|
-
"DataObject": ("O", "O", "O", "O", "RO", "O", "O", "O", "SCGO", "O", "O", "O", "O"),
|
|
250
|
-
"Node": ("ivtfO", "irvtfO", "irvtfO", "irvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "SCGivtfO", "CGirvtfO", "CGirvtfO", "irvtfO"),
|
|
251
|
-
"Device": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "vtfO", "SCGvtfO", "CGIrvtfO", "irvtfO"),
|
|
252
|
-
"SystemSoftware": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "vtfO", "vtfO", "SCGIrvtfO", "irvtfO"),
|
|
253
|
-
"TechnologyService": ("VtfO", "VtfO", "VtfO", "vtfO", "aO", "VtfO", "vtfO", "RvtfO", "aO", "VtfO", "VtfO", "VtfO", "SCGvTFO"),
|
|
254
|
+
"BusinessActor": ("SCGvtfO", "IvtfO", "IvtfO", "IvtfO", "aO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO", "aO"),
|
|
255
|
+
"BusinessProcess": ("vtfO", "SCGvTFO", "CGvTFO", "vTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO", "aO"),
|
|
256
|
+
"BusinessFunction": ("vtfO", "CGvTFO", "SCGvTFO", "vTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO", "aO"),
|
|
257
|
+
"BusinessEvent": ("vtfO", "vTFO", "vTFO", "SCGvTFO", "AO", "vtfO", "vtfO", "vtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO", "aO"),
|
|
258
|
+
"BusinessObject": ("O", "O", "O", "O", "SCGO", "O", "O", "O", "O", "O", "O", "O", "O", "O"),
|
|
259
|
+
"ApplicationComponent": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "SCGRvtfO", "CgrvtfO", "irvtfO", "aO", "vtfO", "vtfO", "vtfO", "vtfO", "aO"),
|
|
260
|
+
"ApplicationInterface": ("VtfO", "vtfO", "vtfO", "vtfO", "aO", "VtfO", "SCGvtfO", "IvtfO", "aO", "VtfO", "VtfO", "VtfO", "vtfO", "aO"),
|
|
261
|
+
"ApplicationService": ("VtfO", "VtfO", "VtfO", "vtfO", "aO", "VtfO", "vtfO", "SCGvTFO", "AO", "VtfO", "VtfO", "VtfO", "vtfO", "aO"),
|
|
262
|
+
"DataObject": ("O", "O", "O", "O", "RO", "O", "O", "O", "SCGO", "O", "O", "O", "O", "O"),
|
|
263
|
+
"Node": ("ivtfO", "irvtfO", "irvtfO", "irvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "SCGivtfO", "CGirvtfO", "CGirvtfO", "irvtfO", "aIO"),
|
|
264
|
+
"Device": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "vtfO", "SCGvtfO", "CGIrvtfO", "irvtfO", "aIO"),
|
|
265
|
+
"SystemSoftware": ("vtfO", "rvtfO", "rvtfO", "rvtfO", "aO", "rvtfO", "rvtfO", "rvtfO", "aO", "vtfO", "vtfO", "SCGIrvtfO", "irvtfO", "aIO"),
|
|
266
|
+
"TechnologyService": ("VtfO", "VtfO", "VtfO", "vtfO", "aO", "VtfO", "vtfO", "RvtfO", "aO", "VtfO", "VtfO", "VtfO", "SCGvTFO", "aO"),
|
|
267
|
+
"Artifact": ("O", "rO", "rO", "rO", "rO", "RO", "rO", "rO", "RO", "O", "O", "RO", "rO", "SCGrO"),
|
|
254
268
|
}
|
|
255
269
|
# fmt: on
|
|
256
270
|
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Generated views (pure): ArchiMate viewpoints per level with a deterministic band layout.
|
|
2
|
+
|
|
3
|
+
Each viewpoint (ArchiMate 3.2 Specification, chapter 13) shows the elements of its types on its level (enterprise or
|
|
4
|
+
solution, from the element's ``levels``) and the relationships on that level; a cross-level link is in no view. A
|
|
5
|
+
detail variant shows the solution elements of its types with their detail elements (property ``level`` = detail). The layout puts the
|
|
6
|
+
layers in horizontal bands (business, application, technology) and the elements of a band in a grid, ordered by
|
|
7
|
+
type and name, each detail element right after its parent, so the same model gives the same view in every run.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
|
|
14
|
+
from .models import Element, Relationship, layer_of
|
|
15
|
+
|
|
16
|
+
ENTERPRISE, SOLUTION, DETAIL = "enterprise", "solution", "detail"
|
|
17
|
+
DEPLOYMENT = frozenset({"ApplicationComponent", "Node", "Device", "SystemSoftware", "TechnologyService"})
|
|
18
|
+
# (view name, viewpoint, element types, level), in export order
|
|
19
|
+
VIEWPOINTS: tuple[tuple[str, str, frozenset[str] | None, str], ...] = (
|
|
20
|
+
("Layered (enterprise)", "Layered", None, ENTERPRISE),
|
|
21
|
+
("Application Cooperation (enterprise)", "Application Cooperation", frozenset({"ApplicationComponent", "ApplicationInterface", "ApplicationService"}), ENTERPRISE),
|
|
22
|
+
("Information Structure (enterprise)", "Information Structure", frozenset({"BusinessObject", "DataObject"}), ENTERPRISE),
|
|
23
|
+
("Implementation and Deployment (enterprise)", "Implementation and Deployment", DEPLOYMENT, ENTERPRISE),
|
|
24
|
+
(
|
|
25
|
+
"Business (enterprise)",
|
|
26
|
+
"Business Process Cooperation",
|
|
27
|
+
frozenset({"BusinessActor", "BusinessProcess", "BusinessFunction", "BusinessEvent", "ApplicationService"}),
|
|
28
|
+
ENTERPRISE,
|
|
29
|
+
),
|
|
30
|
+
("Application Structure (solution)", "Application Structure", frozenset({"ApplicationComponent"}), SOLUTION),
|
|
31
|
+
("Application Cooperation (solution)", "Application Cooperation", frozenset({"ApplicationComponent", "ApplicationInterface"}), SOLUTION),
|
|
32
|
+
("Information Structure (solution)", "Information Structure", frozenset({"DataObject"}), SOLUTION),
|
|
33
|
+
("Implementation and Deployment (solution)", "Implementation and Deployment", DEPLOYMENT, SOLUTION),
|
|
34
|
+
("Information Structure (detail)", "Information Structure", frozenset({"DataObject"}), DETAIL),
|
|
35
|
+
("Implementation and Deployment (detail)", "Implementation and Deployment", DEPLOYMENT | {"Artifact"}, DETAIL),
|
|
36
|
+
# The interfaces with their members (endpoints, pages, jobs); components are left out, their members are above
|
|
37
|
+
("Application Interfaces (detail)", "Application Cooperation", frozenset({"ApplicationInterface"}), DETAIL),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# A view needs an element of its anchor types (the Business view: a business element, not application services alone)
|
|
41
|
+
ANCHORS = {"Business (enterprise)": frozenset({"BusinessActor", "BusinessProcess", "BusinessFunction", "BusinessEvent"})}
|
|
42
|
+
BANDS = ("Business", "Application", "Technology", "Other")
|
|
43
|
+
TYPE_ORDER = (
|
|
44
|
+
"BusinessActor", "BusinessFunction", "BusinessProcess", "BusinessEvent", "BusinessObject",
|
|
45
|
+
"ApplicationComponent", "ApplicationInterface", "ApplicationService", "DataObject",
|
|
46
|
+
"Node", "Device", "SystemSoftware", "TechnologyService", "Artifact",
|
|
47
|
+
) # fmt: skip
|
|
48
|
+
COLUMNS, WIDTH, HEIGHT, GAP, BAND_GAP, MARGIN = 6, 160, 60, 20, 60, 20
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True)
|
|
52
|
+
class ViewNode:
|
|
53
|
+
identifier: str
|
|
54
|
+
element: str
|
|
55
|
+
x: int
|
|
56
|
+
y: int
|
|
57
|
+
w: int = WIDTH
|
|
58
|
+
h: int = HEIGHT
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class ViewConnection:
|
|
63
|
+
identifier: str
|
|
64
|
+
relationship: str
|
|
65
|
+
source: str # node identifiers
|
|
66
|
+
target: str
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class View:
|
|
71
|
+
identifier: str
|
|
72
|
+
name: str
|
|
73
|
+
viewpoint: str
|
|
74
|
+
level: str = ENTERPRISE # enterprise, solution or detail (a detail view shows the detail elements too)
|
|
75
|
+
nodes: list[ViewNode] = field(default_factory=list)
|
|
76
|
+
connections: list[ViewConnection] = field(default_factory=list)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _level(e: Element) -> str:
|
|
80
|
+
return str((e.properties or {}).get("level") or "architect")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _levels(properties: dict | None) -> frozenset[str]:
|
|
84
|
+
"""The levels of an element or relationship: ``level`` detail, else ``levels`` (empty: a cross-level link), else the
|
|
85
|
+
enterprise level (a model from before the levels)."""
|
|
86
|
+
properties = properties or {}
|
|
87
|
+
if properties.get("level") == DETAIL:
|
|
88
|
+
return frozenset({DETAIL})
|
|
89
|
+
levels = properties.get("levels")
|
|
90
|
+
if isinstance(levels, list):
|
|
91
|
+
return frozenset(str(v) for v in levels)
|
|
92
|
+
return frozenset() if properties.get("cross_level") else frozenset({ENTERPRISE})
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _on(level: str, levels: frozenset[str]) -> bool:
|
|
96
|
+
"""Whether something on ``levels`` belongs in a view of ``level`` (a detail view: the solution level and the detail)."""
|
|
97
|
+
return bool(levels & ({SOLUTION, DETAIL} if level == DETAIL else {level}))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _order(e: Element) -> tuple[int, str, str]:
|
|
101
|
+
return (TYPE_ORDER.index(e.element_type) if e.element_type in TYPE_ORDER else len(TYPE_ORDER), e.name.casefold(), e.identifier)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _layout(view: View, shown: list[Element]) -> None:
|
|
105
|
+
by_parent: dict[str, list[Element]] = {}
|
|
106
|
+
for e in shown:
|
|
107
|
+
if _level(e) == "detail":
|
|
108
|
+
by_parent.setdefault(str((e.properties or {}).get("parent") or ""), []).append(e)
|
|
109
|
+
shown_ids = {e.identifier for e in shown}
|
|
110
|
+
y = MARGIN
|
|
111
|
+
for band in BANDS:
|
|
112
|
+
# One group per element type (each starts a new row), every element followed by its detail members
|
|
113
|
+
groups: dict[str, list[Element]] = {}
|
|
114
|
+
for e in sorted((e for e in shown if _level(e) != "detail" and layer_of(e.element_type) == band), key=_order):
|
|
115
|
+
groups.setdefault(e.element_type, []).append(e)
|
|
116
|
+
groups[e.element_type] += sorted(by_parent.get(e.identifier, []), key=_order)
|
|
117
|
+
# Detail elements whose parent is not in the view still get a place, after the band's own
|
|
118
|
+
orphans = (e for e in shown if _level(e) == "detail" and layer_of(e.element_type) == band and str((e.properties or {}).get("parent")) not in shown_ids)
|
|
119
|
+
if rest := sorted(orphans, key=_order):
|
|
120
|
+
groups[""] = rest
|
|
121
|
+
if not groups:
|
|
122
|
+
continue
|
|
123
|
+
for group in groups.values():
|
|
124
|
+
for i, e in enumerate(group):
|
|
125
|
+
row, column = divmod(i, COLUMNS)
|
|
126
|
+
node_id = f"{view.identifier}-n-{e.identifier}"
|
|
127
|
+
view.nodes.append(ViewNode(identifier=node_id, element=e.identifier, x=MARGIN + column * (WIDTH + GAP), y=y + row * (HEIGHT + GAP)))
|
|
128
|
+
y += (len(group) + COLUMNS - 1) // COLUMNS * (HEIGHT + GAP)
|
|
129
|
+
y += BAND_GAP
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def build_views(elements: list[Element], relationships: list[Relationship], relationship_levels: dict[str, frozenset[str]] | None = None) -> list[View]:
|
|
133
|
+
"""The views of the model, one per viewpoint that has elements on its level, in VIEWPOINTS order.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
relationship_levels: Relationship id -> its levels, where the relationship's own properties do not say (the
|
|
137
|
+
export's detail relationships); else from the properties
|
|
138
|
+
"""
|
|
139
|
+
views: list[View] = []
|
|
140
|
+
for number, (name, viewpoint, types, level) in enumerate(VIEWPOINTS, 1):
|
|
141
|
+
shown = [e for e in elements if (types is None or e.element_type in types) and _on(level, _levels(e.properties))]
|
|
142
|
+
anchors = ANCHORS.get(name)
|
|
143
|
+
if not shown or (anchors and not any(e.element_type in anchors for e in shown)) or (level == DETAIL and not any(_level(e) == DETAIL for e in shown)):
|
|
144
|
+
continue
|
|
145
|
+
view = View(identifier=f"view-{number}", name=name, viewpoint=viewpoint, level=level)
|
|
146
|
+
_layout(view, shown)
|
|
147
|
+
node_of = {n.element: n.identifier for n in view.nodes}
|
|
148
|
+
for r in sorted(relationships, key=lambda r: r.identifier):
|
|
149
|
+
on = (relationship_levels or {}).get(r.identifier) or _levels(r.properties)
|
|
150
|
+
if r.source in node_of and r.target in node_of and _on(level, on):
|
|
151
|
+
connection = ViewConnection(identifier=f"{view.identifier}-c-{r.identifier}", relationship=r.identifier, source=node_of[r.source], target=node_of[r.target])
|
|
152
|
+
view.connections.append(connection)
|
|
153
|
+
views.append(view)
|
|
154
|
+
return views
|
|
@@ -8,12 +8,14 @@ Reference: https://www.opengroup.org/archimate-forum/archimate-exchange-format
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
from collections.abc import Mapping, Sequence
|
|
11
12
|
from datetime import datetime
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
|
|
14
15
|
from lxml import etree
|
|
15
16
|
|
|
16
17
|
from .models import Element, Relationship
|
|
18
|
+
from .views import View
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class ArchiMateXMLExporter:
|
|
@@ -47,6 +49,9 @@ class ArchiMateXMLExporter:
|
|
|
47
49
|
output_path: str,
|
|
48
50
|
model_name: str = "ArchiMate Model",
|
|
49
51
|
model_id: str = "model-001",
|
|
52
|
+
properties: Mapping[str, Mapping[str, str]] | None = None,
|
|
53
|
+
views: Sequence[View] | None = None,
|
|
54
|
+
relationship_properties: Mapping[str, Mapping[str, str]] | None = None,
|
|
50
55
|
) -> None:
|
|
51
56
|
"""
|
|
52
57
|
Export ArchiMate model to XML file.
|
|
@@ -57,6 +62,9 @@ class ArchiMateXMLExporter:
|
|
|
57
62
|
output_path: Path to output XML file
|
|
58
63
|
model_name: Name of the model
|
|
59
64
|
model_id: Unique identifier for the model
|
|
65
|
+
properties: Exported properties per element id (e.g. ``level``), declared as propertyDefinitions
|
|
66
|
+
views: Diagrams to export (see ``views.build_views``)
|
|
67
|
+
relationship_properties: Exported properties per relationship id, declared with the element ones
|
|
60
68
|
"""
|
|
61
69
|
# Create root model element
|
|
62
70
|
root = etree.Element(
|
|
@@ -76,17 +84,31 @@ class ArchiMateXMLExporter:
|
|
|
76
84
|
# Add metadata
|
|
77
85
|
self._add_metadata(root)
|
|
78
86
|
|
|
87
|
+
properties = properties or {}
|
|
88
|
+
relationship_properties = relationship_properties or {}
|
|
89
|
+
keys = sorted({key for values in [*properties.values(), *relationship_properties.values()] for key, value in values.items() if value})
|
|
90
|
+
definition_of = {key: f"propid-{key}" for key in keys}
|
|
91
|
+
|
|
79
92
|
# Add elements section
|
|
80
93
|
if elements:
|
|
81
94
|
elements_section = etree.SubElement(root, "elements")
|
|
82
95
|
for element in elements:
|
|
83
|
-
self._add_element(elements_section, element)
|
|
96
|
+
self._add_element(elements_section, element, properties.get(element.identifier, {}), definition_of)
|
|
84
97
|
|
|
85
98
|
# Add relationships section
|
|
86
99
|
if relationships:
|
|
87
100
|
rels_section = etree.SubElement(root, "relationships")
|
|
88
101
|
for relationship in relationships:
|
|
89
|
-
self._add_relationship(rels_section, relationship)
|
|
102
|
+
self._add_relationship(rels_section, relationship, relationship_properties.get(relationship.identifier, {}), definition_of)
|
|
103
|
+
|
|
104
|
+
# The exchange format's order: elements, relationships, organizations, propertyDefinitions, views
|
|
105
|
+
if keys:
|
|
106
|
+
definitions = etree.SubElement(root, "propertyDefinitions")
|
|
107
|
+
for key in keys:
|
|
108
|
+
definition = etree.SubElement(definitions, "propertyDefinition", attrib={"identifier": definition_of[key], "type": "string"})
|
|
109
|
+
etree.SubElement(definition, "name").text = key
|
|
110
|
+
if views:
|
|
111
|
+
self._add_views(root, views, definition_of.get("level"))
|
|
90
112
|
|
|
91
113
|
# Write to file
|
|
92
114
|
tree = etree.ElementTree(root)
|
|
@@ -124,13 +146,21 @@ class ArchiMateXMLExporter:
|
|
|
124
146
|
description = etree.SubElement(metadata, f"{{{self.DC_NS}}}description")
|
|
125
147
|
description.text = "ArchiMate model generated by Deriva from source code analysis"
|
|
126
148
|
|
|
127
|
-
def _add_element(
|
|
149
|
+
def _add_element(
|
|
150
|
+
self,
|
|
151
|
+
parent: etree.Element,
|
|
152
|
+
element: Element,
|
|
153
|
+
properties: Mapping[str, str] | None = None,
|
|
154
|
+
definition_of: Mapping[str, str] | None = None,
|
|
155
|
+
) -> None:
|
|
128
156
|
"""
|
|
129
157
|
Add an element to the XML tree.
|
|
130
158
|
|
|
131
159
|
Args:
|
|
132
160
|
parent: Parent XML element
|
|
133
161
|
element: ArchiMate element to add
|
|
162
|
+
properties: The element's exported properties (key -> value)
|
|
163
|
+
definition_of: propertyDefinition identifier per key
|
|
134
164
|
"""
|
|
135
165
|
elem = etree.SubElement(
|
|
136
166
|
parent,
|
|
@@ -152,17 +182,77 @@ class ArchiMateXMLExporter:
|
|
|
152
182
|
doc_elem.set(f"{{{self.XML_NS}}}lang", "en")
|
|
153
183
|
doc_elem.text = element.documentation
|
|
154
184
|
|
|
155
|
-
#
|
|
156
|
-
#
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
185
|
+
# Only the properties passed in are exported (each needs a model-level propertyDefinition);
|
|
186
|
+
# internal metadata (source, derived_at) on the element is omitted.
|
|
187
|
+
shown = sorted((key, value) for key, value in (properties or {}).items() if value and key in (definition_of or {}))
|
|
188
|
+
if shown and definition_of:
|
|
189
|
+
props = etree.SubElement(elem, "properties")
|
|
190
|
+
for key, value in shown:
|
|
191
|
+
prop = etree.SubElement(props, "property", attrib={"propertyDefinitionRef": definition_of[key]})
|
|
192
|
+
value_elem = etree.SubElement(prop, "value")
|
|
193
|
+
value_elem.set(f"{{{self.XML_NS}}}lang", "en")
|
|
194
|
+
value_elem.text = value
|
|
195
|
+
|
|
196
|
+
def _add_views(self, root: etree.Element, views: Sequence[View], level_definition: str | None = None) -> None:
|
|
197
|
+
"""Add the diagrams: element nodes with their bounds, relationship connections between them, and each view's
|
|
198
|
+
level as a property where the model declares one."""
|
|
199
|
+
diagrams = etree.SubElement(etree.SubElement(root, "views"), "diagrams")
|
|
200
|
+
for view in views:
|
|
201
|
+
diagram = etree.SubElement(
|
|
202
|
+
diagrams,
|
|
203
|
+
"view",
|
|
204
|
+
attrib={"identifier": view.identifier, f"{{{self.XSI_NS}}}type": "Diagram", "viewpoint": view.viewpoint},
|
|
205
|
+
)
|
|
206
|
+
name_elem = etree.SubElement(diagram, "name")
|
|
207
|
+
name_elem.set(f"{{{self.XML_NS}}}lang", "en")
|
|
208
|
+
name_elem.text = view.name
|
|
209
|
+
if level_definition:
|
|
210
|
+
prop = etree.SubElement(etree.SubElement(diagram, "properties"), "property", attrib={"propertyDefinitionRef": level_definition})
|
|
211
|
+
value_elem = etree.SubElement(prop, "value")
|
|
212
|
+
value_elem.set(f"{{{self.XML_NS}}}lang", "en")
|
|
213
|
+
value_elem.text = view.level
|
|
214
|
+
for node in view.nodes:
|
|
215
|
+
etree.SubElement(
|
|
216
|
+
diagram,
|
|
217
|
+
"node",
|
|
218
|
+
attrib={
|
|
219
|
+
"identifier": node.identifier,
|
|
220
|
+
"elementRef": node.element,
|
|
221
|
+
f"{{{self.XSI_NS}}}type": "Element",
|
|
222
|
+
"x": str(node.x),
|
|
223
|
+
"y": str(node.y),
|
|
224
|
+
"w": str(node.w),
|
|
225
|
+
"h": str(node.h),
|
|
226
|
+
},
|
|
227
|
+
)
|
|
228
|
+
for connection in view.connections:
|
|
229
|
+
etree.SubElement(
|
|
230
|
+
diagram,
|
|
231
|
+
"connection",
|
|
232
|
+
attrib={
|
|
233
|
+
"identifier": connection.identifier,
|
|
234
|
+
"relationshipRef": connection.relationship,
|
|
235
|
+
f"{{{self.XSI_NS}}}type": "Relationship",
|
|
236
|
+
"source": connection.source,
|
|
237
|
+
"target": connection.target,
|
|
238
|
+
},
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def _add_relationship(
|
|
242
|
+
self,
|
|
243
|
+
parent: etree.Element,
|
|
244
|
+
relationship: Relationship,
|
|
245
|
+
properties: Mapping[str, str] | None = None,
|
|
246
|
+
definition_of: Mapping[str, str] | None = None,
|
|
247
|
+
) -> None:
|
|
160
248
|
"""
|
|
161
249
|
Add a relationship to the XML tree.
|
|
162
250
|
|
|
163
251
|
Args:
|
|
164
252
|
parent: Parent XML element
|
|
165
253
|
relationship: ArchiMate relationship to add
|
|
254
|
+
properties: The relationship's exported properties (key -> value)
|
|
255
|
+
definition_of: propertyDefinition identifier per key
|
|
166
256
|
"""
|
|
167
257
|
rel = etree.SubElement(
|
|
168
258
|
parent,
|
|
@@ -185,8 +275,15 @@ class ArchiMateXMLExporter:
|
|
|
185
275
|
doc_elem = etree.SubElement(rel, "documentation")
|
|
186
276
|
doc_elem.text = relationship.documentation
|
|
187
277
|
|
|
188
|
-
#
|
|
189
|
-
|
|
278
|
+
# Only the properties passed in are exported (each needs a model-level propertyDefinition), after name and documentation
|
|
279
|
+
shown = sorted((key, value) for key, value in (properties or {}).items() if value and key in (definition_of or {}))
|
|
280
|
+
if shown and definition_of:
|
|
281
|
+
props = etree.SubElement(rel, "properties")
|
|
282
|
+
for key, value in shown:
|
|
283
|
+
prop = etree.SubElement(props, "property", attrib={"propertyDefinitionRef": definition_of[key]})
|
|
284
|
+
value_elem = etree.SubElement(prop, "value")
|
|
285
|
+
value_elem.set(f"{{{self.XML_NS}}}lang", "en")
|
|
286
|
+
value_elem.text = str(value)
|
|
190
287
|
|
|
191
288
|
def export_to_string(
|
|
192
289
|
self,
|
|
@@ -25,10 +25,12 @@ Usage:
|
|
|
25
25
|
|
|
26
26
|
from __future__ import annotations
|
|
27
27
|
|
|
28
|
+
from .db_tool import DATA_DIR
|
|
28
29
|
from .db_tool import export_all as export_database
|
|
29
30
|
from .db_tool import import_all as import_database
|
|
30
31
|
from .manager import (
|
|
31
32
|
DB_PATH,
|
|
33
|
+
ConfigDatabaseBusy,
|
|
32
34
|
ensure_database,
|
|
33
35
|
get_connection,
|
|
34
36
|
init_database,
|
|
@@ -37,7 +39,12 @@ from .manager import (
|
|
|
37
39
|
seed_database,
|
|
38
40
|
)
|
|
39
41
|
|
|
42
|
+
# Bundled business function models (a config path names one of them, or a user-supplied file)
|
|
43
|
+
FUNCTION_MODELS_DIR = DATA_DIR / "function_models"
|
|
44
|
+
|
|
40
45
|
__all__ = [
|
|
46
|
+
"FUNCTION_MODELS_DIR",
|
|
47
|
+
"ConfigDatabaseBusy",
|
|
41
48
|
"ensure_database",
|
|
42
49
|
"get_connection",
|
|
43
50
|
"init_database",
|