pyegeria 5.2.1__py3-none-any.whl → 5.3__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.
- commands/cat/.DS_Store +0 -0
- commands/cat/Dr-Egeria_md-orig.py +166 -0
- commands/cat/__init__.py +23 -0
- commands/cat/dr_egeria_jupyter.py +122 -0
- commands/cat/dr_egeria_md.py +247 -0
- {pyegeria/commands → commands}/cat/exp_list_glossaries.py +3 -4
- {pyegeria/commands → commands}/cat/get_asset_graph.py +4 -4
- {pyegeria/commands → commands}/cat/get_collection.py +8 -9
- {pyegeria/commands → commands}/cat/get_project_dependencies.py +6 -8
- {pyegeria/commands → commands}/cat/get_project_structure.py +6 -8
- {pyegeria/commands → commands}/cat/get_tech_type_elements.py +13 -15
- {pyegeria/commands → commands}/cat/glossary_actions.py +184 -34
- {pyegeria/commands → commands}/cat/list_assets.py +9 -6
- commands/cat/list_categories.py +192 -0
- {pyegeria/commands → commands}/cat/list_cert_types.py +6 -6
- {pyegeria/commands → commands}/cat/list_collections.py +62 -19
- commands/cat/list_data_structures.py +223 -0
- {pyegeria/commands → commands}/cat/list_deployed_catalogs.py +9 -8
- {pyegeria/commands → commands}/cat/list_deployed_database_schemas.py +10 -9
- {pyegeria/commands → commands}/cat/list_deployed_databases.py +9 -8
- pyegeria/commands/cat/list_servers_deployed_imp.py → commands/cat/list_deployed_servers.py +3 -3
- {pyegeria/commands → commands}/cat/list_glossaries.py +57 -15
- {pyegeria/commands → commands}/cat/list_projects.py +5 -5
- {pyegeria/commands → commands}/cat/list_tech_type_elements.py +3 -3
- {pyegeria/commands → commands}/cat/list_tech_types.py +4 -4
- {pyegeria/commands → commands}/cat/list_terms.py +93 -45
- {pyegeria/commands → commands}/cat/list_todos.py +3 -3
- {pyegeria/commands → commands}/cat/list_user_ids.py +9 -8
- {pyegeria/commands → commands}/cli/__init__.py +1 -1
- {pyegeria/commands → commands}/cli/egeria.py +513 -250
- {pyegeria/commands → commands}/cli/egeria_cat.py +128 -51
- {pyegeria/commands → commands}/cli/egeria_login_tui.py +15 -17
- {pyegeria/commands → commands}/cli/egeria_my.py +22 -15
- {pyegeria/commands → commands}/cli/egeria_ops.py +54 -55
- {pyegeria/commands → commands}/cli/egeria_tech.py +364 -152
- {pyegeria/commands → commands}/cli/ops_config.py +18 -11
- commands/my/__init__.py +22 -0
- {pyegeria/commands → commands}/my/list_my_profile.py +6 -8
- {pyegeria/commands → commands}/my/list_my_roles.py +4 -4
- {pyegeria/commands → commands}/my/monitor_my_todos.py +7 -7
- {pyegeria/commands → commands}/my/monitor_open_todos.py +7 -7
- {pyegeria/commands → commands}/my/todo_actions.py +3 -2
- commands/ops/__init__.py +23 -0
- {pyegeria/commands → commands}/ops/gov_server_actions.py +5 -4
- {pyegeria/commands → commands}/ops/list_archives.py +7 -6
- {pyegeria/commands → commands}/ops/list_catalog_targets.py +4 -4
- {pyegeria/commands → commands}/ops/load_archive.py +4 -2
- {pyegeria/commands → commands}/ops/monitor_asset_events.py +8 -7
- {pyegeria/commands → commands}/ops/monitor_engine_activity.py +5 -5
- {pyegeria/commands → commands}/ops/monitor_engine_activity_c.py +3 -3
- {pyegeria/commands → commands}/ops/monitor_gov_eng_status.py +3 -2
- {pyegeria/commands → commands}/ops/monitor_integ_daemon_status.py +23 -15
- {pyegeria/commands → commands}/ops/monitor_platform_status.py +5 -4
- {pyegeria/commands → commands}/ops/monitor_server_startup.py +7 -7
- {pyegeria/commands → commands}/ops/monitor_server_status.py +16 -11
- {pyegeria/commands → commands}/ops/orig_monitor_server_list.py +2 -2
- {pyegeria/commands → commands}/ops/orig_monitor_server_status.py +3 -3
- {pyegeria/commands → commands}/ops/refresh_integration_daemon.py +4 -4
- {pyegeria/commands → commands}/ops/restart_integration_daemon.py +3 -3
- {pyegeria/commands → commands}/ops/table_integ_daemon_status.py +3 -3
- commands/tech/__init__.py +22 -0
- commands/tech/generic_actions.py +74 -0
- {pyegeria/commands → commands}/tech/get_element_info.py +5 -7
- {pyegeria/commands → commands}/tech/get_guid_info.py +4 -5
- {pyegeria/commands → commands}/tech/get_tech_details.py +8 -9
- {pyegeria/commands → commands}/tech/get_tech_type_template.py +4 -4
- pyegeria/commands/tech/list_elements.py → commands/tech/list_all_om_type_elements.py +11 -10
- pyegeria/commands/tech/list_elements_x.py → commands/tech/list_all_om_type_elements_x.py +11 -12
- pyegeria/commands/tech/list_related_elements.py → commands/tech/list_all_related_elements.py +11 -9
- {pyegeria/commands → commands}/tech/list_anchored_elements.py +16 -16
- {pyegeria/commands → commands}/tech/list_asset_types.py +4 -4
- commands/tech/list_elements_by_classification_by_property_value.py +200 -0
- commands/tech/list_elements_by_property_value.py +180 -0
- commands/tech/list_elements_by_property_value_x.py +201 -0
- {pyegeria/commands → commands}/tech/list_elements_for_classification.py +11 -9
- {pyegeria/commands → commands}/tech/list_gov_action_processes.py +5 -6
- commands/tech/list_information_supply_chains.py +167 -0
- {pyegeria/commands → commands}/tech/list_registered_services.py +3 -3
- commands/tech/list_related_elements_with_prop_value.py +221 -0
- {pyegeria/commands → commands}/tech/list_related_specification.py +3 -3
- {pyegeria/commands → commands}/tech/list_relationship_types.py +4 -5
- {pyegeria/commands → commands}/tech/list_relationships.py +3 -3
- commands/tech/list_solution_blueprints.py +181 -0
- commands/tech/list_solution_components.py +185 -0
- commands/tech/list_solution_roles.py +184 -0
- {pyegeria/commands → commands}/tech/list_tech_templates.py +3 -3
- {pyegeria/commands → commands}/tech/list_valid_metadata_values.py +5 -6
- {pyegeria/commands → commands}/tech/table_tech_templates.py +16 -13
- {pyegeria/commands → commands}/tech/x_list_related_elements.py +6 -4
- md_processing/__init__.py +49 -0
- md_processing/data/commands.json +3252 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +254 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +696 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +254 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +298 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +608 -0
- md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +94 -0
- md_processing/dr_egeria_inbox/archive/freddie_intro.md +284 -0
- md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +275 -0
- md_processing/dr_egeria_inbox/archive/test-term.md +110 -0
- md_processing/dr_egeria_inbox/cat_test.md +100 -0
- md_processing/dr_egeria_inbox/data_field.md +54 -0
- md_processing/dr_egeria_inbox/data_spec.md +77 -0
- md_processing/dr_egeria_inbox/data_spec_test.md +2406 -0
- md_processing/dr_egeria_inbox/data_test.md +86 -0
- md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +168 -0
- md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +280 -0
- md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +313 -0
- md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +1073 -0
- md_processing/dr_egeria_inbox/dr_egeria_isc1.md +44 -0
- md_processing/dr_egeria_inbox/glossary_creation_experiment.ipynb +341 -0
- md_processing/dr_egeria_inbox/glossary_test1.md +324 -0
- md_processing/dr_egeria_inbox/rel.md +8 -0
- md_processing/dr_egeria_inbox/sb.md +119 -0
- md_processing/dr_egeria_inbox/search_test.md +39 -0
- md_processing/dr_egeria_inbox/solution-components.md +154 -0
- md_processing/dr_egeria_inbox/solution_blueprints.md +118 -0
- md_processing/dr_egeria_inbox/synonym_test.md +42 -0
- md_processing/dr_egeria_inbox/t2.md +268 -0
- md_processing/dr_egeria_outbox/processed-2025-05-15 19:52-data_test.md +94 -0
- md_processing/dr_egeria_outbox/processed-2025-05-16 07:39-data_test.md +88 -0
- md_processing/dr_egeria_outbox/processed-2025-05-17 16:01-data_field.md +56 -0
- md_processing/dr_egeria_outbox/processed-2025-05-18 15:51-data_test.md +103 -0
- md_processing/dr_egeria_outbox/processed-2025-05-18 16:47-data_test.md +94 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:14-data_test.md +96 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:20-data_test.md +100 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 07:22-data_test.md +88 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 09:26-data_test.md +91 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 10:27-data_test.md +91 -0
- md_processing/dr_egeria_outbox/processed-2025-05-19 14:04-data_test.md +91 -0
- md_processing/md_commands/__init__.py +3 -0
- md_processing/md_commands/blueprint_commands.py +303 -0
- md_processing/md_commands/data_designer_commands.py +1182 -0
- md_processing/md_commands/glossary_commands.py +1144 -0
- md_processing/md_commands/project_commands.py +163 -0
- md_processing/md_processing_utils/__init__.py +4 -0
- md_processing/md_processing_utils/common_md_proc_utils.py +724 -0
- md_processing/md_processing_utils/common_md_utils.py +172 -0
- md_processing/md_processing_utils/extraction_utils.py +486 -0
- md_processing/md_processing_utils/md_processing_constants.py +128 -0
- md_processing/md_processing_utils/message_constants.py +19 -0
- pyegeria/.DS_Store +0 -0
- pyegeria/__init__.py +231 -146
- pyegeria/_client.py +36 -13
- pyegeria/_exceptions.py +55 -46
- pyegeria/_globals.py +11 -1
- pyegeria/_validators.py +5 -5
- pyegeria/asset_catalog_omvs.py +78 -21
- pyegeria/automated_curation_omvs.py +11 -6
- pyegeria/classification_manager_omvs.py +41 -37
- pyegeria/collection_manager_omvs.py +722 -705
- pyegeria/core_omag_server_config.py +1 -1
- pyegeria/create_tech_guid_lists.py +13 -13
- pyegeria/data_designer_omvs.py +5104 -0
- pyegeria/dr.egeria spec.md +9 -0
- pyegeria/egeria_cat_client.py +5 -8
- pyegeria/egeria_client.py +39 -24
- pyegeria/egeria_config_client.py +2 -1
- pyegeria/egeria_my_client.py +4 -4
- pyegeria/egeria_tech_client.py +40 -18
- pyegeria/feedback_manager_omvs.py +1 -1
- pyegeria/full_omag_server_config.py +5 -3
- pyegeria/glossary_browser_omvs.py +1915 -694
- pyegeria/glossary_manager_omvs.py +685 -1842
- pyegeria/m_test.py +118 -0
- pyegeria/md_processing_helpers.py +58 -0
- pyegeria/md_processing_utils.py +2147 -0
- pyegeria/md_processing_utils_orig.py +1103 -0
- pyegeria/mermaid_utilities.py +1194 -14
- pyegeria/metadata_explorer_omvs.py +5 -50
- pyegeria/my_profile_omvs.py +3 -2
- pyegeria/output_formatter.py +389 -0
- pyegeria/platform_services.py +5 -5
- pyegeria/project_manager_omvs.py +97 -18
- pyegeria/runtime_manager_omvs.py +8 -10
- pyegeria/server_operations.py +2 -2
- pyegeria/solution_architect_omvs.py +2156 -0
- pyegeria/template_manager_omvs.py +13 -13
- pyegeria/utils.py +3 -1
- pyegeria/valid_metadata_omvs.py +5 -4
- pyegeria/x_action_author_omvs.py +3 -6
- {pyegeria-5.2.1.dist-info → pyegeria-5.3.dist-info}/METADATA +9 -8
- pyegeria-5.3.dist-info/RECORD +196 -0
- {pyegeria-5.2.1.dist-info → pyegeria-5.3.dist-info}/WHEEL +1 -1
- pyegeria-5.3.dist-info/entry_points.txt +99 -0
- pyegeria/commands/README.md +0 -47
- pyegeria/commands/__init__.py +0 -22
- pyegeria/commands/cat/__init__.py +0 -1
- pyegeria/commands/doc/README.md +0 -145
- pyegeria/commands/doc/Visual Command Reference/README.md +0 -511
- pyegeria/commands/doc/Visual Command Reference/cat/show/assets/asset-graph 2024-11-20 at 15.56.42.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/assets/assets-in-domain 2024-11-20 at 15.49.55@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/assets/elements-of-type 2024-11-20 at 16.01.35.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/assets/tech-type-elements 2024-11-20 at 16.05.05.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-data-catalogs 2024-12-17 at 15.43.27@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-data-catalogs-2024-11-20 at 16.17.43@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-schemas 2024-11-25 at 20.14.50@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-schemas 2024-12-17 at 15.48.38@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-servers 2024-11-25 at 20.21.25@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed-servers 2024-12-17 at 15.52.16@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/deployed-data/deployed_databases 2024-12-16 at 16.40.31@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/glossary/list-glossaries 2024-11-25 at 20.30.02.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/glossary/list-terms 2024-11-25 at 20.32.11.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/asset-types 2024-11-25 at 20.34.19@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/certification-types 2024-11-25 at 20.37.07.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/collection-graph 2024-12-12 at 11.33.18@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/list-collections 2024-12-10 at 14.25.51@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/list-todos 2024-12-12 at 11.46.30@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/list-user-ids 2024-12-12 at 11.51.09@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/info/tech-types 2024-12-12 at 11.37.20@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/projects/project_dependencies 2024-12-14 at 16.24.39@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/projects/project_structure 2024-12-14 at 16.21.35@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/cat/show/projects/projects 2024-12-14 at 16.18.10@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/hey_egeria tui 2024-12-16 at 16.58.22@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/my/show/my_profile 2024-12-14 at 16.29.27@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/my/show/my_roles 2024-12-14 at 16.32.10@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/my/show/my_todos 2024-12-15 at 16.24.13@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/my/show/open_todos 2024-12-14 at 16.36.12@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/engines/list_engine_activity compressed 2024-12-15 at 16.48.48@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_activity 2024-12-15 at 16.32.55@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_activity compressed 2024-12-15 at 16.38.29@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/engines/monitor_engine_status 2024-12-15 at 16.51.26.jpeg +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/integrations/monitor_integration_daemon_status 2024-12-15 at 16.57.12@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/integrations/monitor_integration_targets 2024-12-15 at 17.02.19@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/platforms/monitor_platform_status 2024-12-15 at 19.53.18@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/servers/monitor_server_status 2024-12-15 at 19.59.39@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/servers/monitor_server_status full 2024-12-15 at 20.01.57@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/ops/show/servers/monitor_startup_servers 2024-12-15 at 19.56.07@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/get_anchored_elements 2024-12-15 at 21.25.41@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/get_elements_of_om_type 2024-12-16 at 14.39.59@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/info_for_guid 2024-12-16 at 11.35.29@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/list_elements_by_om-type 2024-12-16 at 14.24.18@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/list_elements_by_om-type extended 2024-12-16 at 14.28.46@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/list_elements_of_om_type_by_classification 2024-12-16 at 14.35.26@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/related_elements 2024-12-16 at 14.55.01@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/elements/show_related_specifications 2024-12-16 at 15.04.55@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/asset_types 2024-12-16 at 15.10.16@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/detailed_governance_action_processes 2024-12-16 at 15.16.26@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/governance_action_processes 2024-12-16 at 15.13.01@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/registered_services 2024-12-16 at 16.44.54@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/relationship_types 2024-12-16 at 16.20.34@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/relationship_types 2024-12-19 at 10.51.54@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-info/valid_metadata_values 2024-12-16 at 15.31.56@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-types/list_tech_type_template_specs 2024-12-16 at 16.03.22@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-types/list_technology_types 2024-12-16 at 15.39.20@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-types/tech_type_details 2024-12-16 at 15.37.21@2x.png +0 -0
- pyegeria/commands/doc/Visual Command Reference/tech/show/tech-types/tech_type_templates 2024-12-16 at 16.11.48@2x.png +0 -0
- pyegeria/commands/doc/glossary/basic-glossary-tui.md +0 -109
- pyegeria/commands/doc/glossary/images/delete-glossary-step1 2024-11-06 at 15.47.23@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/delete-glossary-step2 2024-11-06 at 15.51.29@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/delete-glossary-step3 2024-11-06 at 15.53.19@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/delete-glossary-step4 2024-11-06 at 15.55.11@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/out-create-glossary example 2024-11-05 at 20.38.04@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/out-create-term 2024-11-06 at 20.48.29.png +0 -0
- pyegeria/commands/doc/glossary/images/out-delete-term 2024-11-07 at 03.57.25.png +0 -0
- pyegeria/commands/doc/glossary/images/out-display-terms-for-glossary-test 2024-11-06 at 20.51.28.png +0 -0
- pyegeria/commands/doc/glossary/images/out-export-example 2024-11-07 at 09.54.57.png +0 -0
- pyegeria/commands/doc/glossary/images/out-exported-terms 2024-11-06 at 21.06.32.png +0 -0
- pyegeria/commands/doc/glossary/images/out-glossary-list example 2024-11-05 at 20.41.02@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/out-import-terms 2024-11-07 at 08.15.18.png +0 -0
- pyegeria/commands/doc/glossary/images/out-list-all-terms 2024-11-06 at 16.22.20@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/out-list-terms-for-example 2024-11-06 at 16.40.12.png +0 -0
- pyegeria/commands/doc/glossary/images/out-list-terms-second 2024-11-06 at 16.45.13.png +0 -0
- pyegeria/commands/doc/glossary/images/out-pipx install pyegeria 2024-11-10 at 18.12.21.png +0 -0
- pyegeria/commands/doc/glossary/images/out-server-status-full 2024-11-10 at 18.25.14.png +0 -0
- pyegeria/commands/doc/glossary/images/out-servers-status 2024-11-10 at 18.15.42.png +0 -0
- pyegeria/commands/doc/glossary/images/out-upsert-import 2024-11-07 at 19.37.00.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-2024-11-10 at 18.26.29.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-create-glossary example 2024-11-05 at 20.34.24@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-create-term 2024-11-06 at 20.46.35.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-delete-term 2024-11-07 at 03.51.57.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-display-terms-for-example 2024-11-06 at 20.56.49.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-export-example 2024-11-07 at 09.52.59.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-hey-egeria 2024-11-10 at 18.31.01.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-import-upsert-example 2024-11-07 at 10.08.37.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-list-terms-second 2024-11-06 at 16.46.34.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-load-archive.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-server-status-full 2024-11-10 at 19.14.36.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-show-glossaries 2024-11-07 at 20.00.05.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-show-glossary-terms 2024-11-05 at 19.37.53@2x.png +0 -0
- pyegeria/commands/doc/glossary/images/tui-upsert 2024-11-07 at 11.49.04.png +0 -0
- pyegeria/commands/doc/glossary/images/upsert-example.om-terms 2024-11-07 at 11.44.05.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/README.md +0 -346
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/CleanShot 2024-11-18 at 21.32.03@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/Xmind 1731421782704.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/Xmind 1731422134920.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/hey_egeria 2024-11-12 at 20.38.43.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/hey_egeria cat 2024-11-12 at 21.41.43.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/out-integ-status-list 2024-11-12 at 16.45.26.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/out-integ-status-live 2024-11-12 at 16.44.12@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/out-server-status 2024-11-10 at 18.15.42@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/out-server-status-full 2024-11-10 at 18.25.14@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/short-cut commands 2024-11-12 at 22.22.13.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-hey-egeria.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-integration-status-paging.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-load-archive 2024-11-10 at 19.19.09@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-show-server-status 2024-11-10 at 18.52.01@2x.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-show-server-status-full 2024-11-10.png +0 -0
- pyegeria/commands/doc/hey_egeria: a pyegeria command line interface/images/tui-status-paging 2024-11-12 at 16.26.14@2x.png +0 -0
- pyegeria/commands/ops/__init__.py +0 -22
- pyegeria/commands/tech/__init__.py +0 -0
- pyegeria-5.2.1.dist-info/RECORD +0 -232
- pyegeria-5.2.1.dist-info/entry_points.txt +0 -81
- {pyegeria/commands → commands}/cat/README.md +0 -0
- {pyegeria/commands → commands}/cli/txt_custom_v2.tcss +0 -0
- {pyegeria/commands → commands}/my/README.md +0 -0
- {pyegeria/commands → commands}/ops/README.md +0 -0
- {pyegeria/commands → commands}/ops/x_engine_actions.py +0 -0
- {pyegeria/commands → commands}/tech/README.md +0 -0
- /pyegeria/commands/my/__init__.py → /md_processing/dr_egeria_inbox/t1.md +0 -0
- {pyegeria-5.2.1.dist-info → pyegeria-5.3.dist-info}/LICENSE +0 -0
@@ -0,0 +1,2147 @@
|
|
1
|
+
"""
|
2
|
+
|
3
|
+
This file contains functions to parse and process Egeria Markdown (Freddie)
|
4
|
+
|
5
|
+
|
6
|
+
"""
|
7
|
+
import json
|
8
|
+
import os
|
9
|
+
import re
|
10
|
+
import sys
|
11
|
+
from datetime import datetime
|
12
|
+
from typing import List, Optional, Any
|
13
|
+
|
14
|
+
from rich import print
|
15
|
+
from rich.console import Console
|
16
|
+
from rich.markdown import Markdown
|
17
|
+
|
18
|
+
from pyegeria import body_slimmer
|
19
|
+
from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND, DEBUG_LEVEL)
|
20
|
+
from pyegeria.egeria_tech_client import EgeriaTech
|
21
|
+
from md_processing.md_processing_utils.md_processing_constants import (message_types,
|
22
|
+
pre_command, EXISTS_REQUIRED, load_commands, get_command_spec, get_attribute, get_attribute_labels, get_alternate_names)
|
23
|
+
|
24
|
+
|
25
|
+
from pyegeria.project_manager_omvs import ProjectManager
|
26
|
+
|
27
|
+
ALWAYS = "ALWAYS"
|
28
|
+
ERROR = "ERROR"
|
29
|
+
INFO = "INFO"
|
30
|
+
WARNING = "WARNING"
|
31
|
+
pre_command = "\n---\n==> Processing object_action:"
|
32
|
+
command_seperator = Markdown("\n---\n")
|
33
|
+
EXISTS_REQUIRED = "Exists Required"
|
34
|
+
|
35
|
+
|
36
|
+
EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
|
37
|
+
console = Console(width=EGERIA_WIDTH)
|
38
|
+
|
39
|
+
command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms", "List Term Details",
|
40
|
+
"List Glossary Terms", "List Term History", "List Term Revision History", "List Term Update History",
|
41
|
+
"List Glossary Structure", "List Glossaries", "List Categories", "List Glossary Categories",
|
42
|
+
"Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
|
43
|
+
"Create Solution Blueprint", "Update Solution Blueprint", "Create Solution Component",
|
44
|
+
"Update Solution Component", "Create Term-Term Relationship", "Update Term-Term Relationship",]
|
45
|
+
# verbosity - verbose, quiet, debug
|
46
|
+
|
47
|
+
message_types = {
|
48
|
+
"INFO": "INFO-", "WARNING": "WARNING->", "ERROR": "ERROR->", "DEBUG-INFO": "DEBUG-INFO->",
|
49
|
+
"DEBUG-WARNING": "DEBUG-WARNING->", "DEBUG-ERROR": "DEBUG-ERROR->", "ALWAYS": "\n\n==> "
|
50
|
+
}
|
51
|
+
ALWAYS = "ALWAYS"
|
52
|
+
ERROR = "ERROR"
|
53
|
+
INFO = "INFO"
|
54
|
+
WARNING = "WARNING"
|
55
|
+
pre_command = "\n---\n==> Processing object_action:"
|
56
|
+
command_seperator = Markdown("\n---\n")
|
57
|
+
EXISTS_REQUIRED = "Exists Required"
|
58
|
+
|
59
|
+
GLOSSARY_NAME_LABELS = ["Glossary Name", "Glossary", "Glossaries", "Owning Glossary", "In Glossary"]
|
60
|
+
CATEGORY_NAME_LABELS = ["Glossary Category Name", "Glossary Category", "Glossary Categories", "Category Name",
|
61
|
+
"Category", "Categories"]
|
62
|
+
PARENT_CATEGORY_LABELS = ["Parent Category Name", "Parent Category", "parent category name", "parent category"]
|
63
|
+
CHILD_CATEGORY_LABELS = ["Child Categories", "Child Category", "child category names", "child categories",
|
64
|
+
"Child Category Names"]
|
65
|
+
TERM_NAME_LABELS = ["Glossary Term Name", "Glossary Term", "Glossary Terms", "Term Name", "Term", "Terms", "Term Names"]
|
66
|
+
PROJECT_NAME_LABELS = ["Project Name", "Project", "Project Names", "Projects"]
|
67
|
+
BLUEPRINT_NAME_LABELS = ["Solution Blueprint Name", "Solution Blueprint", "Solution Blueprints", "Blueprint Name",
|
68
|
+
"Blueprint", "Blueprints"]
|
69
|
+
COMPONENT_NAME_LABELS = ["Solution Component Name", "Solution Component", "Solution Components", "Component Name",
|
70
|
+
"Component", "Components", "Parent Components", "Parent Component"]
|
71
|
+
SOLUTION_ROLE_LABELS = ["Solution Role Name", "Solution Role", "Solution Roles", "Role Name", "Role", "Roles"]
|
72
|
+
SOLUTION_ACTOR_ROLE_LABELS = ["Solution Actor Role Name", "Solution Actor Role Names", "Solution Actor Role",
|
73
|
+
"Solution Actor Roles", "Actor Role Name", "Actor Role", "Actor Roles",
|
74
|
+
"Actor Role Names"]
|
75
|
+
SOLUTION_LINKING_ROLE_LABELS = ["Solution Linking Role Name", "Solution Linking Role Names", "Solution Linking Role",
|
76
|
+
"Solution Linking Roles", "Linking Role Name", "Linking Role", "Linking Roles",
|
77
|
+
"Linking Role Names"]
|
78
|
+
OUTPUT_LABELS = ["Output", "Output Format"]
|
79
|
+
SEARCH_LABELS = ['Search String', 'Filter']
|
80
|
+
GUID_LABELS = ['GUID', 'guid']
|
81
|
+
|
82
|
+
ELEMENT_OUTPUT_FORMATS = ["LIST", "DICT", "MD", "FORM", "REPORT"]
|
83
|
+
TERM_RELATIONSHPS = [
|
84
|
+
"Synonym",
|
85
|
+
"Translation",
|
86
|
+
"PreferredTerm",
|
87
|
+
"TermISATYPEOFRelationship",
|
88
|
+
"TermTYPEDBYRelationship",
|
89
|
+
"Antonym",
|
90
|
+
"ReplacementTerm",
|
91
|
+
"ValidValue",
|
92
|
+
"TermHASARelationship",
|
93
|
+
"RelatedTerm",
|
94
|
+
"ISARelationship"
|
95
|
+
]
|
96
|
+
|
97
|
+
# Dictionary to store element information to avoid redundant API calls
|
98
|
+
element_dictionary = {}
|
99
|
+
|
100
|
+
|
101
|
+
def get_element_dictionary():
|
102
|
+
"""
|
103
|
+
Get the shared element dictionary.
|
104
|
+
|
105
|
+
Returns:
|
106
|
+
dict: The shared element dictionary
|
107
|
+
"""
|
108
|
+
global element_dictionary
|
109
|
+
return element_dictionary
|
110
|
+
|
111
|
+
|
112
|
+
def update_element_dictionary(key, value):
|
113
|
+
"""
|
114
|
+
Update the shared element dictionary with a new key-value pair.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
key (str): The key to update
|
118
|
+
value (dict): The value to associate with the key
|
119
|
+
"""
|
120
|
+
global element_dictionary
|
121
|
+
if (key is None or value is None):
|
122
|
+
print(f"===>ERROR Key is {key} and value is {value}")
|
123
|
+
return
|
124
|
+
element_dictionary[key] = value
|
125
|
+
|
126
|
+
|
127
|
+
def clear_element_dictionary():
|
128
|
+
"""
|
129
|
+
Clear the shared element dictionary.
|
130
|
+
"""
|
131
|
+
global element_dictionary
|
132
|
+
element_dictionary.clear()
|
133
|
+
|
134
|
+
|
135
|
+
def is_present(value: str) -> bool:
|
136
|
+
global element_dictionary
|
137
|
+
present = value in element_dictionary.keys() or any(
|
138
|
+
value in inner_dict.values() for inner_dict in element_dictionary.values())
|
139
|
+
return present
|
140
|
+
|
141
|
+
|
142
|
+
def find_key_with_value(value: str) -> str | None:
|
143
|
+
"""
|
144
|
+
Finds the top-level key whose nested dictionary contains the given value.
|
145
|
+
|
146
|
+
Args:
|
147
|
+
data (dict): A dictionary where keys map to nested dictionaries.
|
148
|
+
value (str): The value to search for.
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
str | None: The top-level key that contains the value, or None if not found.
|
152
|
+
"""
|
153
|
+
global element_dictionary
|
154
|
+
# Check if the value matches a top-level key
|
155
|
+
if value in element_dictionary.keys():
|
156
|
+
return value
|
157
|
+
|
158
|
+
# Check if the value exists in any of the nested dictionaries
|
159
|
+
for key, inner_dict in element_dictionary.items():
|
160
|
+
if value in inner_dict.values():
|
161
|
+
return key
|
162
|
+
|
163
|
+
return None # If value not found
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
def render_markdown(markdown_text: str) -> None:
|
169
|
+
"""Renders the given markdown text in the console."""
|
170
|
+
console.print(Markdown(markdown_text))
|
171
|
+
|
172
|
+
|
173
|
+
def is_valid_iso_date(date_text) -> bool:
|
174
|
+
"""Checks if the given string is a valid ISO date."""
|
175
|
+
try:
|
176
|
+
datetime.strptime(date_text, '%Y-%m-%d')
|
177
|
+
return True
|
178
|
+
except ValueError:
|
179
|
+
return False
|
180
|
+
|
181
|
+
debug_level = DEBUG_LEVEL
|
182
|
+
|
183
|
+
def set_debug_level(directive: str) -> None:
|
184
|
+
"""Sets the debug level for the script."""
|
185
|
+
global debug_level
|
186
|
+
if directive == "display":
|
187
|
+
debug_level = "display-only"
|
188
|
+
|
189
|
+
|
190
|
+
def get_current_datetime_string():
|
191
|
+
"""Returns the current date and time as a human-readable string."""
|
192
|
+
now = datetime.now().strftime('%Y-%m-%d %H:%M')
|
193
|
+
return now
|
194
|
+
|
195
|
+
|
196
|
+
def update_term_categories(egeria_client: EgeriaTech, term_guid: str, categories_exist: bool,
|
197
|
+
categories_list: List[str]) -> None:
|
198
|
+
"""
|
199
|
+
|
200
|
+
Adds or removes a term to/from specified categories in a glossary.
|
201
|
+
|
202
|
+
This function associates a term, identified by its GUID, with one or more
|
203
|
+
categories. It uses the provided EgeriaTech client to assign the term
|
204
|
+
to the categories. If the GUID of a category is not readily available, it
|
205
|
+
is retrieved either from a pre-loaded dictionary or through a client lookup.
|
206
|
+
|
207
|
+
Args:
|
208
|
+
egeria_client (EgeriaTech): The client to interact with the glossary.
|
209
|
+
term_guid (str): The GUID of the term to be associated with categories.
|
210
|
+
categories_exist (bool): Flag indicating whether the categories already
|
211
|
+
exist.
|
212
|
+
categories_list (List[str]): A list of category names to associate with
|
213
|
+
the term.
|
214
|
+
|
215
|
+
Returns:
|
216
|
+
None
|
217
|
+
"""
|
218
|
+
to_be_cat_guids: list[str] = []
|
219
|
+
# find the categories a term is currently in.
|
220
|
+
existing_categories = egeria_client.get_categories_for_term(term_guid)
|
221
|
+
if type(existing_categories) is str:
|
222
|
+
current_categories = []
|
223
|
+
else:
|
224
|
+
current_categories = [cat['elementHeader']['guid'] for cat in existing_categories]
|
225
|
+
|
226
|
+
if categories_exist is True and categories_list is not None:
|
227
|
+
if type(categories_list) is str:
|
228
|
+
categories_list = categories_list.split(",").trim()
|
229
|
+
for category in categories_list:
|
230
|
+
cat_guid = None
|
231
|
+
cat_el = category.strip()
|
232
|
+
element_dict = get_element_dictionary()
|
233
|
+
if cat_el in element_dict:
|
234
|
+
cat = element_dict.get(cat_el, None)
|
235
|
+
cat_guid = cat.get('guid', None) if cat else None
|
236
|
+
if cat_guid is None:
|
237
|
+
cat_guid = egeria_client.__get_guid__(qualified_name=cat_el)
|
238
|
+
update_element_dictionary(cat_el, {'guid': cat_guid})
|
239
|
+
to_be_cat_guids.append(cat_guid)
|
240
|
+
|
241
|
+
for cat in to_be_cat_guids:
|
242
|
+
if cat not in current_categories:
|
243
|
+
egeria_client.add_term_to_category(term_guid, cat)
|
244
|
+
current_categories.append(cat)
|
245
|
+
msg = f"Added term {term_guid} to category {cat}"
|
246
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
247
|
+
|
248
|
+
for cat in current_categories:
|
249
|
+
if cat not in to_be_cat_guids:
|
250
|
+
egeria_client.remove_term_from_category(term_guid, cat)
|
251
|
+
msg = f"Removed term {term_guid} from category {cat}"
|
252
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
253
|
+
else: # No categories specified - so remove any categories a term is in
|
254
|
+
for cat in current_categories:
|
255
|
+
egeria_client.remove_term_from_category(term_guid, cat)
|
256
|
+
msg = f"Removed term {term_guid} from category {cat}"
|
257
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
258
|
+
|
259
|
+
|
260
|
+
def extract_command_plus(block: str) -> tuple[str, str, str] | None:
|
261
|
+
"""
|
262
|
+
Extracts a multi-word object and its associated action from the given block of text.
|
263
|
+
|
264
|
+
This function searches for a pattern in the format of `#...##` or `#...\n`
|
265
|
+
inside the provided string `block`. The matched pattern is split into
|
266
|
+
two parts: the action and the object type. The action is expected to
|
267
|
+
be the first part, while the rest is treated as the object type. If
|
268
|
+
no match is found, the function returns None.
|
269
|
+
|
270
|
+
Lines beginning with '>' are ignored.
|
271
|
+
|
272
|
+
Args:
|
273
|
+
block: A string containing the block of text to search for the
|
274
|
+
object_action and action.
|
275
|
+
|
276
|
+
Returns:
|
277
|
+
A tuple containing the object_action, the object type and the object action if a
|
278
|
+
match is found. Otherwise, returns None.
|
279
|
+
"""
|
280
|
+
# Filter out lines beginning with '>'
|
281
|
+
filtered_lines = [line for line in block.split('\n') if not line.strip().startswith('>')]
|
282
|
+
filtered_block = '\n'.join(filtered_lines)
|
283
|
+
|
284
|
+
match = re.search(r"#(.*?)(?:##|\n|$)", filtered_block) # Using a non capturing group
|
285
|
+
if match:
|
286
|
+
clean_match = match.group(1).strip()
|
287
|
+
if ' ' in clean_match:
|
288
|
+
parts = clean_match.split(' ')
|
289
|
+
object_action = parts[0].strip()
|
290
|
+
# Join the rest of the parts to allow object_type to be one or two words
|
291
|
+
object_type = ' '.join(parts[1:]).strip()
|
292
|
+
else:
|
293
|
+
object_type = clean_match.split(' ')[1].strip()
|
294
|
+
object_action = clean_match.split(' ')[0].strip()
|
295
|
+
|
296
|
+
return clean_match, object_type, object_action
|
297
|
+
return None
|
298
|
+
|
299
|
+
|
300
|
+
def extract_command(block: str) -> str | None:
|
301
|
+
"""
|
302
|
+
Extracts a object_action from a block of text that is contained between a single hash ('#') and
|
303
|
+
either a double hash ('##'), a newline character, or the end of the string.
|
304
|
+
|
305
|
+
The function searches for a specific pattern within the block of text and extracts the
|
306
|
+
content that appears immediately after a single hash ('#'). Ensures that the extracted
|
307
|
+
content is appropriately trimmed of leading or trailing whitespace, if present.
|
308
|
+
|
309
|
+
Args:
|
310
|
+
block: A string representing the block of text to process. Contains the content
|
311
|
+
in which the object_action and delimiters are expected to be present.
|
312
|
+
|
313
|
+
Returns:
|
314
|
+
The extracted object_action as a string if a match is found, otherwise None.
|
315
|
+
"""
|
316
|
+
match = re.search(r"#(.*?)(?:##|\n|$)", block) # Using a non capturing group
|
317
|
+
if match:
|
318
|
+
return match.group(1).strip()
|
319
|
+
return None
|
320
|
+
|
321
|
+
|
322
|
+
def extract_attribute(text: str, labels: list[str]) -> str | None:
|
323
|
+
"""
|
324
|
+
Extracts the attribute value from a string.
|
325
|
+
|
326
|
+
Args:
|
327
|
+
text: The input string.
|
328
|
+
labels: List of equivalent labels to search for
|
329
|
+
|
330
|
+
Returns:
|
331
|
+
The value of the attribute, or None if not found.
|
332
|
+
|
333
|
+
Note:
|
334
|
+
Lines beginning with '>' are ignored.
|
335
|
+
"""
|
336
|
+
# Iterate over the list of labels
|
337
|
+
for label in labels:
|
338
|
+
# Construct pattern for the current label
|
339
|
+
pattern = rf"## {re.escape(label)}\n(.*?)(?:#|___|>|$)" # modified from --- to enable embedded tables
|
340
|
+
match = re.search(pattern, text, re.DOTALL)
|
341
|
+
if match:
|
342
|
+
# Extract matched text
|
343
|
+
matched_text = match.group(1).strip()
|
344
|
+
|
345
|
+
# Filter out lines beginning with '>'
|
346
|
+
filtered_lines = [line for line in matched_text.split('\n') if not line.strip().startswith('>')]
|
347
|
+
filtered_text = '\n'.join(filtered_lines)
|
348
|
+
|
349
|
+
# Replace consecutive \n with a single \n
|
350
|
+
extracted_text = re.sub(r'\n+', '\n', filtered_text)
|
351
|
+
if not extracted_text.isspace() and extracted_text:
|
352
|
+
return extracted_text.trim() # Return the cleaned text - I removed the title casing
|
353
|
+
|
354
|
+
return None
|
355
|
+
|
356
|
+
|
357
|
+
def print_msg(msg_level: str, msg: str, verbosity: str):
|
358
|
+
"""
|
359
|
+
Prints a message based on its type and verbosity level.
|
360
|
+
|
361
|
+
This function handles the output of messages depending on the specified
|
362
|
+
verbosity level and message type. It uses predefined message types and
|
363
|
+
formats the output accordingly.
|
364
|
+
|
365
|
+
Args:
|
366
|
+
msg_type: The type of the message, such as 'WARNING', 'ERROR', 'INFO', or
|
367
|
+
'ALWAYS'.
|
368
|
+
msg: The content of the message to display.
|
369
|
+
verbosity: The verbosity level, which determines how the message is
|
370
|
+
displayed ('verbose', 'quiet', or 'debug').
|
371
|
+
"""
|
372
|
+
msg_level = msg_level.upper()
|
373
|
+
record = f"{message_types[msg_level]} {msg}"
|
374
|
+
if msg_level in ("WARNING", "ERROR", "INFO"):
|
375
|
+
record = f"* {record}"
|
376
|
+
|
377
|
+
match verbosity.lower():
|
378
|
+
case "verbose":
|
379
|
+
if msg_level in ("WARNING", "ERROR", "INFO", "ALWAYS"):
|
380
|
+
print(record)
|
381
|
+
case "quiet":
|
382
|
+
if msg_level in ("WARNING", "ERROR", "ALWAYS"):
|
383
|
+
print(record)
|
384
|
+
case "debug":
|
385
|
+
print(record)
|
386
|
+
case "display-only":
|
387
|
+
pass
|
388
|
+
case _:
|
389
|
+
print("Invalid verbosity level - exiting\n")
|
390
|
+
sys.exit(1)
|
391
|
+
|
392
|
+
|
393
|
+
def process_simple_attribute(txt: str, labels: list[str], if_missing: str = INFO) -> str | None:
|
394
|
+
"""Process a simple attribute based on the provided labels and if_missing value.
|
395
|
+
Extract the attribute value from the text and return it if it exists.
|
396
|
+
If it doesn`t exist, return None and print an error message with severity of if_missing.
|
397
|
+
|
398
|
+
Parameters:
|
399
|
+
----------
|
400
|
+
txt: str
|
401
|
+
The block of object_action text to extract attributes from.
|
402
|
+
labels: list
|
403
|
+
The possible attribute labels to search for. The first label will be used in messages.
|
404
|
+
if_missing: str, default is INFO
|
405
|
+
Can be one of "WARNING", "ERROR", "INFO". The severity of the missing attribute.
|
406
|
+
"""
|
407
|
+
if if_missing not in ["WARNING", "ERROR", "INFO"]:
|
408
|
+
print_msg("ERROR", "Invalid severity for missing attribute", debug_level)
|
409
|
+
return None
|
410
|
+
|
411
|
+
attribute = extract_attribute(txt, labels)
|
412
|
+
|
413
|
+
if attribute is None:
|
414
|
+
if if_missing == INFO:
|
415
|
+
msg = f"Optional attribute {labels[0]} missing"
|
416
|
+
else:
|
417
|
+
msg = f"Missing {labels[0]} attribute"
|
418
|
+
print_msg(if_missing, msg, debug_level)
|
419
|
+
return None
|
420
|
+
return attribute
|
421
|
+
|
422
|
+
|
423
|
+
def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid: str) -> str:
|
424
|
+
"""
|
425
|
+
Updates a object_action by modifying the input text with corresponding actions, GUID, and qualified name.
|
426
|
+
The function processes the provided object_action based on the given parameters, updating the relevant
|
427
|
+
sections in the text, including object_action actions, GUID, qualified name, and optionally the status
|
428
|
+
of the attributes. It ensures that proper formatting and necessary fields are present in the text.
|
429
|
+
|
430
|
+
Args:
|
431
|
+
txt (str): The input text containing the content to be updated.
|
432
|
+
command (str): The object_action to be processed (e.g., "Create Term", "Update Term").
|
433
|
+
obj_type (str): The object type related to the object_action (e.g., "Term", "Category").
|
434
|
+
q_name (str): The qualified name to be added or updated in the text.
|
435
|
+
u_guid (str): The unique identifier (GUID) to be added or updated in the text. If not provided,
|
436
|
+
it defaults to an empty string.
|
437
|
+
|
438
|
+
Returns:
|
439
|
+
str: The updated text containing the modifications based on the provided object_action.
|
440
|
+
|
441
|
+
"""
|
442
|
+
u_guid = u_guid if u_guid else " "
|
443
|
+
verb = command.split(' ')[0].strip()
|
444
|
+
action = "Update" if (verb == "Create" and u_guid is not None) else "Create"
|
445
|
+
txt = txt.replace(f"{command}", f'{action} {obj_type}\n') # update the object_action
|
446
|
+
|
447
|
+
if "Qualified Name" not in txt:
|
448
|
+
txt += f"\n## Qualified Name\n{q_name}\n"
|
449
|
+
if "GUID" not in txt:
|
450
|
+
txt += f"\n## GUID\n{u_guid}\n"
|
451
|
+
|
452
|
+
status = extract_attribute(txt, ["Status"])
|
453
|
+
if command in ["Create Term", "Update Term"] and status is None:
|
454
|
+
pattern = r"(## Status\s*\n)(.*?)(#)"
|
455
|
+
replacement = r"\1\n DRAFT\n\n\3"
|
456
|
+
txt = re.sub(pattern, replacement, txt)
|
457
|
+
return txt
|
458
|
+
|
459
|
+
|
460
|
+
def process_provenance_command(file_path: str, txt: [str]) -> str:
|
461
|
+
"""This md_commands processes a provenence object_action by pre-pending the current file name and time to the provenance
|
462
|
+
output"""
|
463
|
+
output = (f"* Derived from processing file {file_path} on "
|
464
|
+
f"{get_current_datetime_string()}\n")
|
465
|
+
pattern = rf"# {re.escape('Provenance')}\n(.*?)(?:#|---|$)"
|
466
|
+
match = re.search(pattern, txt, re.DOTALL)
|
467
|
+
if match:
|
468
|
+
# Extract matched text and replace consecutive \n with a single \n
|
469
|
+
extracted_text = re.sub(r'\n+', '\n', match.group(1).strip())
|
470
|
+
if not extracted_text.isspace() and extracted_text:
|
471
|
+
existing_prov = extracted_text # Return the cleaned text
|
472
|
+
else:
|
473
|
+
existing_prov = None
|
474
|
+
|
475
|
+
existing_prov = existing_prov if existing_prov else " "
|
476
|
+
return f"\n# Provenance:\n{existing_prov}\n{output}\n"
|
477
|
+
|
478
|
+
|
479
|
+
def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: list[str], txt: str,
|
480
|
+
action: str, version: str = None) -> tuple[str, str, bool, bool]:
|
481
|
+
"""
|
482
|
+
Processes element identifiers by extracting display name and qualified name from the input text,
|
483
|
+
checking if the element exists in Egeria, and validating the information.
|
484
|
+
|
485
|
+
Parameters
|
486
|
+
----------
|
487
|
+
egeria_client: EgeriaTech
|
488
|
+
Client object for interacting with Egeria.
|
489
|
+
element_type: str
|
490
|
+
type of element to process (e.g., 'blueprint', 'category', 'term')
|
491
|
+
element_labels: a list of equivalent label names to use in processing the element.
|
492
|
+
txt: str
|
493
|
+
A string representing the input text to be processed for extracting element identifiers.
|
494
|
+
action: str
|
495
|
+
The action object_action to be executed (e.g., 'Create', 'Update', 'Display', ...)
|
496
|
+
version: str, optional = None
|
497
|
+
An optional version identifier used if we need to construct the qualified name
|
498
|
+
|
499
|
+
Returns: tuple[str, str, str, bool, bool]
|
500
|
+
A tuple containing:
|
501
|
+
- qualified_name: Empty string or element identifier
|
502
|
+
- guid: Empty string or additional element information
|
503
|
+
- Valid: Boolean indicating if the element information is valid
|
504
|
+
- Exists: Boolean indicating if the element exists in Egeria
|
505
|
+
"""
|
506
|
+
valid = True
|
507
|
+
|
508
|
+
element_name = extract_attribute(txt, element_labels)
|
509
|
+
qualified_name = extract_attribute(txt, ["Qualified Name"])
|
510
|
+
|
511
|
+
if qualified_name:
|
512
|
+
q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type,
|
513
|
+
qualified_name) # Qualified name could be different if it
|
514
|
+
# is being updated
|
515
|
+
else:
|
516
|
+
q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type, element_name)
|
517
|
+
if unique is False:
|
518
|
+
msg = f"Multiple elements named {element_name} found"
|
519
|
+
print_msg("DEBUG-ERROR", msg, debug_level)
|
520
|
+
valid = False
|
521
|
+
|
522
|
+
if action == "Update" and not exists:
|
523
|
+
msg = f"Element {element_name} does not exist"
|
524
|
+
print_msg("DEBUG-ERROR", msg, debug_level)
|
525
|
+
valid = False
|
526
|
+
|
527
|
+
elif action == "Update" and exists:
|
528
|
+
msg = f"Element {element_name} exists"
|
529
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
530
|
+
|
531
|
+
elif action == "Create" and exists:
|
532
|
+
msg = f"Element {element_name} already exists"
|
533
|
+
print_msg("DEBUG-ERROR", msg, debug_level)
|
534
|
+
valid = False
|
535
|
+
|
536
|
+
elif action == "Create" and not exists:
|
537
|
+
msg = f"{element_type} `{element_name}` does not exist"
|
538
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
539
|
+
|
540
|
+
if q_name is None and qualified_name is None:
|
541
|
+
q_name = egeria_client.__create_qualified_name__(element_type, element_name, version_identifier=version)
|
542
|
+
update_element_dictionary(q_name, {'display_name': element_name})
|
543
|
+
elif qualified_name:
|
544
|
+
update_element_dictionary(qualified_name, {'display_name': element_name})
|
545
|
+
elif action == EXISTS_REQUIRED:
|
546
|
+
if not exists:
|
547
|
+
msg = f"Required {element_type} `{element_name}` does not exist"
|
548
|
+
print_msg("DEBUG-ERROR", msg, debug_level)
|
549
|
+
valid = False
|
550
|
+
else:
|
551
|
+
msg = f"Required {element_type} `{element_name}` exists"
|
552
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
553
|
+
valid = True
|
554
|
+
|
555
|
+
return q_name, guid, valid, exists
|
556
|
+
|
557
|
+
|
558
|
+
def get_element_by_name(egeria_client, element_type: str, element_name: str) -> tuple[
|
559
|
+
str | None, str | None, bool | None, bool | None]:
|
560
|
+
"""
|
561
|
+
Generalized function to retrieve an element by name based on its type.
|
562
|
+
|
563
|
+
Parameters:
|
564
|
+
egeria_client: Client
|
565
|
+
Client object for interacting with Egeria.
|
566
|
+
element_type: str
|
567
|
+
The type of element to retrieve (e.g., 'blueprint', 'category', 'term').
|
568
|
+
element_name: str
|
569
|
+
The name of the element to retrieve.
|
570
|
+
|
571
|
+
Returns:
|
572
|
+
tuple of qualified_name, guid, uniqye, exists
|
573
|
+
"""
|
574
|
+
unique = None
|
575
|
+
|
576
|
+
element_dict = get_element_dictionary()
|
577
|
+
q_name = find_key_with_value(element_name)
|
578
|
+
if q_name: # use information from element_dictionary
|
579
|
+
guid = element_dict[q_name].get('guid', None)
|
580
|
+
unique = True
|
581
|
+
exists = True
|
582
|
+
if guid is not None: # Found complete entry in element_dictionary
|
583
|
+
msg = f'Found {element_type} qualified name and guid in element_dictionary for `{element_name}`'
|
584
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
585
|
+
return q_name, guid, unique, exists
|
586
|
+
|
587
|
+
else: # Missing guid from element_dictionary
|
588
|
+
guid = egeria_client.get_element_guid_by_unique_name(element_name)
|
589
|
+
if guid == NO_ELEMENTS_FOUND:
|
590
|
+
guid = None
|
591
|
+
msg = f"No {element_type} guid found with name {element_name} in Egeria"
|
592
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
593
|
+
|
594
|
+
return q_name, guid, unique, exists
|
595
|
+
else:
|
596
|
+
exists = True
|
597
|
+
update_element_dictionary(q_name, {'guid': guid})
|
598
|
+
msg = f"Found guid value of {guid} for {element_name} in Egeria"
|
599
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
600
|
+
|
601
|
+
return q_name, guid, unique, exists
|
602
|
+
|
603
|
+
# Haven't seen this element before
|
604
|
+
property_names = ['qualifiedName', 'name', 'displayName']
|
605
|
+
open_metadata_type_name = None
|
606
|
+
details = egeria_client.get_elements_by_property_value(element_name, property_names, open_metadata_type_name)
|
607
|
+
if isinstance(details, str):
|
608
|
+
msg = f"{element_type} `{element_name}` not found in Egeria"
|
609
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
610
|
+
exists = False
|
611
|
+
return None, None, unique, exists
|
612
|
+
if len(details) > 1:
|
613
|
+
msg = (f"More than one element with name {element_name} found, please specify a "
|
614
|
+
f"**Qualified Name**")
|
615
|
+
print_msg("DEBUG-ERROR", msg, debug_level)
|
616
|
+
unique = False
|
617
|
+
exists = None
|
618
|
+
return element_name, None, unique, exists
|
619
|
+
|
620
|
+
el_qname = details[0]["properties"].get('qualifiedName', None)
|
621
|
+
el_guid = details[0]['elementHeader']['guid']
|
622
|
+
el_display_name = details[0]["properties"].get('displayName', None)
|
623
|
+
update_element_dictionary(el_qname, {
|
624
|
+
'guid': el_guid, 'displayName': el_display_name
|
625
|
+
})
|
626
|
+
msg = f"Found {element_type} `{el_display_name}` with qualified name `{el_qname}`"
|
627
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
628
|
+
exists = True
|
629
|
+
unique = True
|
630
|
+
return el_qname, el_guid, unique, exists
|
631
|
+
|
632
|
+
# Convert element_type to plural form for method name construction # if element_type.endswith('y'): # # # #
|
633
|
+
# plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{ # # #
|
634
|
+
# element_type}es" # else: # plural_type = f"{element_type}s" # # # Construct method name # method_name
|
635
|
+
# = f"get_{plural_type}_by_name" # # # Check if the method exists on the client # if hasattr(egeria_client,
|
636
|
+
# method_name): # # Call the method # method = getattr(egeria_client, method_name) # result = #
|
637
|
+
# method(element_name) # return result # else: # # Method doesn't exist # return f"Method { # #
|
638
|
+
# method_name} not found on client"
|
639
|
+
|
640
|
+
|
641
|
+
def process_name_list(egeria_client: EgeriaTech, element_type: str, txt: str, element_labels: list[str]) -> tuple[str,
|
642
|
+
list[Any], bool | Any, bool | None | Any] | None:
|
643
|
+
"""
|
644
|
+
Processes a list of names specified in the given text, retrieves details for each
|
645
|
+
element based on the provided type, and generates a list of valid qualified names.
|
646
|
+
|
647
|
+
The function reads a text block, extracts a list of element names according to the specified
|
648
|
+
element type, looks them up using the provided Egeria client, and classifies them as valid or
|
649
|
+
invalid. It returns the processed names, a list of qualified names, and validity and existence
|
650
|
+
flags.
|
651
|
+
|
652
|
+
Args:
|
653
|
+
|
654
|
+
egeria_client (EgeriaTech): The client instance to connect and query elements from an
|
655
|
+
external system.
|
656
|
+
Element_type (str): The type of element, such as schema or attribute, to process.
|
657
|
+
Txt (str): The raw input text containing element names to be processed.
|
658
|
+
element_labels: a list of equivalent label names to use in processing the element.
|
659
|
+
|
660
|
+
Returns:
|
661
|
+
tuple[str | None, list | None, bool, bool]: A tuple containing:
|
662
|
+
- Concatenated valid input names as a single string (or None if empty).
|
663
|
+
- A list of known qualified names extracted from the processed elements.
|
664
|
+
- A boolean indicating whether all elements are valid.
|
665
|
+
- A boolean indicating whether all elements exist.
|
666
|
+
"""
|
667
|
+
valid = True
|
668
|
+
exists = True
|
669
|
+
elements = ""
|
670
|
+
new_element_list = []
|
671
|
+
|
672
|
+
elements_txt = extract_attribute(txt, element_labels)
|
673
|
+
|
674
|
+
if elements_txt is None:
|
675
|
+
msg = f"No {element_type} found"
|
676
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
677
|
+
|
678
|
+
else:
|
679
|
+
element_list = re.split(r'[,\n]+', elements_txt)
|
680
|
+
|
681
|
+
for element in element_list:
|
682
|
+
element_el = element.strip()
|
683
|
+
|
684
|
+
# Get the element using the generalized function
|
685
|
+
known_q_name, known_guid, el_valid, el_exists = get_element_by_name(egeria_client, element_type, element_el)
|
686
|
+
# print_msg("DEBUG-INFO", status_msg, debug_level)
|
687
|
+
|
688
|
+
if el_exists and el_valid:
|
689
|
+
elements = f"{element_el} {elements}" # list of the input names
|
690
|
+
new_element_list.append(known_q_name) # list of qualified names
|
691
|
+
elif not el_exists:
|
692
|
+
msg = f"No {element_type} `{element_el}` found"
|
693
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
694
|
+
valid = False
|
695
|
+
valid = valid if el_valid is None else (valid and el_valid)
|
696
|
+
exists = exists and el_exists
|
697
|
+
|
698
|
+
if elements:
|
699
|
+
# elements += "\n"
|
700
|
+
msg = f"Found {element_type}: {elements}"
|
701
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
702
|
+
else:
|
703
|
+
msg = f" Name list contains one or more invalid qualified names."
|
704
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
705
|
+
return elements, new_element_list, valid, exists
|
706
|
+
|
707
|
+
|
708
|
+
def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
709
|
+
"""
|
710
|
+
Processes a blueprint create or update object_action by extracting key attributes such as
|
711
|
+
blueprint name, description, and version from the given cell.
|
712
|
+
|
713
|
+
Parameters:
|
714
|
+
egeria_client: SolutionArchitect
|
715
|
+
Client object for interacting with Egeria.
|
716
|
+
txt: str
|
717
|
+
A string representing the input cell to be processed for
|
718
|
+
extracting element attributes.
|
719
|
+
directive: str, optional, default "display"
|
720
|
+
An optional string indicating the directive to be used - display, validate, or execute
|
721
|
+
|
722
|
+
Returns: str
|
723
|
+
A string summarizing the outcome of the processing.
|
724
|
+
"""
|
725
|
+
command, object_type, object_action = extract_command_plus(txt)
|
726
|
+
set_debug_level(directive)
|
727
|
+
display_name = process_simple_attribute(txt, ['Display Name', 'Blueprint Name'], ERROR)
|
728
|
+
description = process_simple_attribute(txt, ['Description'])
|
729
|
+
version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
|
730
|
+
|
731
|
+
print(
|
732
|
+
Markdown(f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `"
|
733
|
+
f"{directive}`\n"))
|
734
|
+
if display_name is None:
|
735
|
+
valid = False
|
736
|
+
q_name, known_guid, exists = None
|
737
|
+
else:
|
738
|
+
element_labels = BLUEPRINT_NAME_LABELS
|
739
|
+
element_labels.append('Display Name')
|
740
|
+
q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels, txt,
|
741
|
+
object_action, version)
|
742
|
+
|
743
|
+
element_display = (f"\n* Command: {object_action} {object_type}\n\t* Blueprint: {display_name}\n\t"
|
744
|
+
f"* Description: {description}\n\t"
|
745
|
+
f"* Version: {version}\n\t* Qualified Name:{q_name}\n\t* GUID: {known_guid} "
|
746
|
+
# f"\n\t* Update Description: {update_description}\n"
|
747
|
+
)
|
748
|
+
|
749
|
+
if valid:
|
750
|
+
msg = f"\n-->It is valid to **{object_action}** element \'{display_name}\'\n"
|
751
|
+
print_msg("ALWAYS", msg, debug_level)
|
752
|
+
if directive == "display":
|
753
|
+
print(Markdown(element_display))
|
754
|
+
return None
|
755
|
+
elif directive == "validate":
|
756
|
+
print(Markdown(element_display))
|
757
|
+
return valid
|
758
|
+
|
759
|
+
elif directive == "process":
|
760
|
+
print(Markdown(element_display))
|
761
|
+
try:
|
762
|
+
if not valid: # First validate the element before we process it
|
763
|
+
msg = "\nInvalid input found - please review the errors and warnings above\n"
|
764
|
+
print_msg("ERROR", msg, debug_level)
|
765
|
+
return None
|
766
|
+
|
767
|
+
if object_action == "Update" and directive == "process":
|
768
|
+
if not exists:
|
769
|
+
msg = f"\n-->Update failed - Blueprint {display_name} does not exist"
|
770
|
+
print_msg("ERROR", msg, debug_level)
|
771
|
+
return None
|
772
|
+
|
773
|
+
# call update blueprint here
|
774
|
+
|
775
|
+
msg = f"\nUpdated Blueprint `{display_name}` with GUID {known_guid}"
|
776
|
+
print_msg("ALWAYS", msg, debug_level)
|
777
|
+
|
778
|
+
# update with get blueprint by guid
|
779
|
+
return 'Would return get blueprint by guid and return md' # egeria_client.get_term_by_guid( # # #
|
780
|
+
# known_guid, 'md')
|
781
|
+
|
782
|
+
elif object_action == "Update" and directive == "validate":
|
783
|
+
return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # # #
|
784
|
+
# known_guid, 'md')
|
785
|
+
|
786
|
+
elif object_action == "Create":
|
787
|
+
if exists:
|
788
|
+
msg = f"\n{WARNING}Blueprint {display_name} exists and result document updated"
|
789
|
+
print_msg("WARNING", msg, debug_level)
|
790
|
+
return update_a_command(txt, f"{object_type}{object_action}", object_type, q_name, known_guid)
|
791
|
+
else:
|
792
|
+
# create the blueprint
|
793
|
+
# term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
|
794
|
+
# if term_guid == NO_ELEMENTS_FOUND:
|
795
|
+
# print(f"{ERROR}Term {term_name} not created")
|
796
|
+
# return None
|
797
|
+
new_guid = f"guid:{get_current_datetime_string()}"
|
798
|
+
msg = f"\nCreated Blueprint `{display_name}`with GUID {new_guid}"
|
799
|
+
print_msg("ALWAYS", msg, debug_level)
|
800
|
+
|
801
|
+
update_element_dictionary(q_name, {'guid': new_guid, 'display_name': display_name})
|
802
|
+
return 'Would return get blueprint by guid results as md' # egeria_client.get_term_by_guid( #
|
803
|
+
# term_guid, 'MD')
|
804
|
+
else:
|
805
|
+
return None
|
806
|
+
|
807
|
+
except Exception as e:
|
808
|
+
msg = f"{ERROR}Error creating term {display_name}: {e}"
|
809
|
+
print_msg("ERROR", msg, debug_level)
|
810
|
+
console.print_exception(show_locals=True)
|
811
|
+
return None
|
812
|
+
else:
|
813
|
+
return None
|
814
|
+
|
815
|
+
|
816
|
+
def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
|
817
|
+
Optional[str]:
|
818
|
+
"""
|
819
|
+
Processes a solution componentt create or update object_action by extracting key attributes such as
|
820
|
+
solution component name, description, version, solution component type etc from the given cell.
|
821
|
+
|
822
|
+
Parameters:
|
823
|
+
egeria_client: SolutionArchitect
|
824
|
+
Client object for interacting with Egeria.
|
825
|
+
txt: str
|
826
|
+
A string representing the input cell to be processed for
|
827
|
+
extracting element attributes.
|
828
|
+
directive: str, optional, default "display"
|
829
|
+
An optional string indicating the directive to be used - display, validate or execute
|
830
|
+
|
831
|
+
Returns: str
|
832
|
+
A string summarizing the outcome of the processing.
|
833
|
+
"""
|
834
|
+
set_debug_level(directive)
|
835
|
+
bp_qname_list = []
|
836
|
+
command, object_type, object_action = extract_command_plus(txt)
|
837
|
+
|
838
|
+
display_name = process_simple_attribute(txt, ['Display Name', 'Solution Component Name'], ERROR)
|
839
|
+
description = process_simple_attribute(txt, ['Description'])
|
840
|
+
version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
|
841
|
+
solution_component_type = process_simple_attribute(txt, ['Solution Component Type'])
|
842
|
+
planned_deployed_implementation_type = process_simple_attribute(txt, ['Planned Deployment Implementation Type'])
|
843
|
+
solution_blueprints = process_simple_attribute(txt, ['Solution Blueprints'])
|
844
|
+
parent_components = process_simple_attribute(txt, ['Parent Components'])
|
845
|
+
|
846
|
+
print(Markdown(
|
847
|
+
f"{pre_command} {object_action} `{object_type}` for Solution Component: `\'{display_name}\'` with directive: "
|
848
|
+
f"`{directive}`\n"))
|
849
|
+
|
850
|
+
if display_name is None:
|
851
|
+
valid = False
|
852
|
+
q_name, known_guid, exists = None
|
853
|
+
else:
|
854
|
+
element_labels = COMPONENT_NAME_LABELS
|
855
|
+
element_labels.append('Display Name')
|
856
|
+
known_q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type,
|
857
|
+
element_labels, txt, object_action,
|
858
|
+
version)
|
859
|
+
|
860
|
+
if solution_blueprints: # Find information about blueprints that include this component
|
861
|
+
msg = "Checking for blueprints that include this solution component"
|
862
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
863
|
+
solution_blueprints, bp_qname_list, bp_valid, bp_exist = process_name_list(egeria_client, 'Solution Blueprints',
|
864
|
+
txt, BLUEPRINT_NAME_LABELS)
|
865
|
+
if bp_exist and bp_valid:
|
866
|
+
msg = f"Found valid blueprints that include this solution component:\n\t{solution_blueprints}"
|
867
|
+
print_msg("INFO", msg, debug_level)
|
868
|
+
else:
|
869
|
+
msg = f"No valid blueprints that include this solution component found."
|
870
|
+
print_msg("INFO", msg, debug_level)
|
871
|
+
if parent_components is None:
|
872
|
+
msg = f"Parent Components are missing"
|
873
|
+
print_msg("INFO", msg, debug_level)
|
874
|
+
else:
|
875
|
+
parent_components, parent_qname_list, parents_valid, parent_components_exist = process_name_list(egeria_client,
|
876
|
+
'Parent '
|
877
|
+
'Components',
|
878
|
+
txt,
|
879
|
+
COMPONENT_NAME_LABELS)
|
880
|
+
if parent_components_exist and parents_valid:
|
881
|
+
msg = f"Found valid parent components that include this solution component:\n\t{parent_qname_list}"
|
882
|
+
print_msg("INFO", msg, debug_level)
|
883
|
+
else:
|
884
|
+
msg = f"No valid parent components that include this solution component found."
|
885
|
+
print_msg("INFO", msg, debug_level)
|
886
|
+
|
887
|
+
element_display = (f"* Command: {object_action} {object_type}\n\t* Display Name: {display_name}\n\t"
|
888
|
+
f"* Description: {description}\n\t"
|
889
|
+
f"* Version Identifier: {version}\n\t"
|
890
|
+
f"* Solution Component Type {solution_component_type}\n\t"
|
891
|
+
f"* Planned Deployment Implementation Type {planned_deployed_implementation_type}\n\t"
|
892
|
+
f"* Solution_Blueprints: {solution_blueprints}\n\t"
|
893
|
+
f"* Parent Components: {parent_components}\n\t"
|
894
|
+
f"* Qualified Name:{known_q_name}\n\t* GUID: {known_guid} "
|
895
|
+
# f"\n\t* Update Description: {update_description}"
|
896
|
+
)
|
897
|
+
|
898
|
+
if object_action == "Update": # check to see if provided information exists and is consistent with existing info
|
899
|
+
if not exists:
|
900
|
+
msg = f"Element {display_name} does not exist with input:\n"
|
901
|
+
print_msg("ERROR", msg, debug_level)
|
902
|
+
valid = False
|
903
|
+
elif not valid:
|
904
|
+
msg = (f"\n-->Validation checks failed in updating {object_type} \'{display_name}\' with: \n"
|
905
|
+
f"{element_display}")
|
906
|
+
print_msg("ERROR", msg, debug_level)
|
907
|
+
else: # it exists and is valid
|
908
|
+
msg = f"\n-->It is valid to update {object_type} \'{display_name}\' with: \n"
|
909
|
+
print_msg("ALWAYS", msg, debug_level)
|
910
|
+
if known_q_name is None:
|
911
|
+
known_q_name = egeria_client.__create_qualified_name__(object_type, display_name,
|
912
|
+
version_identifier=version)
|
913
|
+
update_element_dictionary(known_q_name, {'display_name': display_name, 'guid': known_guid})
|
914
|
+
|
915
|
+
elif object_action == 'Create': # if the object_action is create, check that it doesn't already exist
|
916
|
+
if exists:
|
917
|
+
msg = f"{object_type} `{display_name}` already exists."
|
918
|
+
print_msg("ERROR", msg, debug_level)
|
919
|
+
valid = False
|
920
|
+
elif not valid:
|
921
|
+
msg = f"\n-->Validation checks failed in creating element \'{display_name}\' with: \n"
|
922
|
+
print_msg("ERROR", msg, debug_level)
|
923
|
+
else: # valid to create - update element_dictionary
|
924
|
+
msg = f"\n-->It is valid to create element \'{display_name}\' with: \n"
|
925
|
+
print_msg("ALWAYS", msg, debug_level)
|
926
|
+
if known_q_name is None:
|
927
|
+
known_q_name = egeria_client.__create_qualified_name__(object_type, display_name,
|
928
|
+
version_identifier=version)
|
929
|
+
update_element_dictionary(known_q_name, {'display_name': display_name})
|
930
|
+
print(Markdown(element_display))
|
931
|
+
if directive == "display":
|
932
|
+
return None
|
933
|
+
elif directive == "validate":
|
934
|
+
return valid
|
935
|
+
|
936
|
+
elif directive == "process":
|
937
|
+
try:
|
938
|
+
if not valid: # First validate the term before we process it
|
939
|
+
return None
|
940
|
+
|
941
|
+
if object_action == "Update" and directive == "process":
|
942
|
+
if not exists:
|
943
|
+
msg = (f"\n-->Solution Component {display_name} does not exist")
|
944
|
+
print_msg("ERROR", msg, debug_level)
|
945
|
+
return None
|
946
|
+
|
947
|
+
# call update solution component here
|
948
|
+
|
949
|
+
msg = f"\nUpdated Solution Component `{display_name}` with GUID {known_guid}"
|
950
|
+
print_msg("ALWAYS", msg, debug_level)
|
951
|
+
# update with get solution component by guid
|
952
|
+
return 'Would return get Solution Component by guid and return md' # # # #
|
953
|
+
# egeria_client.get_term_by_guid(known_guid, 'md')
|
954
|
+
|
955
|
+
elif object_action == "Update" and directive == "validate":
|
956
|
+
return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # # #
|
957
|
+
# known_guid, 'md')
|
958
|
+
|
959
|
+
elif object_action == "Create":
|
960
|
+
if exists:
|
961
|
+
f"\n{WARNING}Component {display_name} exists and result document updated"
|
962
|
+
print_msg("WARNING", msg, debug_level)
|
963
|
+
return update_a_command(txt, f"{object_type}{object_action}", object_type, known_q_name, known_guid)
|
964
|
+
else:
|
965
|
+
# create the solution component
|
966
|
+
# term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, term_body)
|
967
|
+
# if term_guid == NO_ELEMENTS_FOUND:
|
968
|
+
# print(f"{ERROR}Term {term_name} not created")
|
969
|
+
# return None
|
970
|
+
|
971
|
+
msg = f"\nCreated Solution Component `{display_name}` with GUID {known_guid}"
|
972
|
+
print_msg("ALWAYS", msg, debug_level)
|
973
|
+
update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
|
974
|
+
return 'Would return get solution component by guid results as md' # # # #
|
975
|
+
# egeria_client.get_term_by_guid(term_guid, 'MD')
|
976
|
+
|
977
|
+
except Exception as e:
|
978
|
+
msg = f"Error creating term {display_name}: {e}"
|
979
|
+
print_msg("ERROR", msg, debug_level)
|
980
|
+
console.print_exception(show_locals=True)
|
981
|
+
return None
|
982
|
+
else:
|
983
|
+
return None
|
984
|
+
|
985
|
+
def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
986
|
+
"""
|
987
|
+
Processes a glossary create or update object_action by extracting key attributes such as
|
988
|
+
glossary name, language, description, and usage from the given text.
|
989
|
+
|
990
|
+
:param txt: A string representing the input cell to be processed for
|
991
|
+
extracting glossary-related attributes.
|
992
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
993
|
+
:return: A string summarizing the outcome of the processing.
|
994
|
+
"""
|
995
|
+
|
996
|
+
command, object_type, object_action = extract_command_plus(txt)
|
997
|
+
set_debug_level(directive)
|
998
|
+
|
999
|
+
glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
|
1000
|
+
print(Markdown(
|
1001
|
+
f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `"
|
1002
|
+
f"{directive}` "))
|
1003
|
+
language = process_simple_attribute(txt, ['Language'], INFO)
|
1004
|
+
description = process_simple_attribute(txt, ['Description'], INFO)
|
1005
|
+
usage = process_simple_attribute(txt, ['Usage'], INFO)
|
1006
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
|
1007
|
+
valid = True
|
1008
|
+
|
1009
|
+
if glossary_name is None:
|
1010
|
+
valid = False
|
1011
|
+
known_q_name = None
|
1012
|
+
known_guid = None
|
1013
|
+
glossary_exists = False
|
1014
|
+
else:
|
1015
|
+
element_labels = GLOSSARY_NAME_LABELS
|
1016
|
+
element_labels.append('Display Name')
|
1017
|
+
known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,
|
1018
|
+
element_labels, txt,
|
1019
|
+
object_action, None)
|
1020
|
+
glossary_display = (f"\n* Command: `{command}`\n\t* Glossary Name: {glossary_name}\n\t"
|
1021
|
+
f"* Language: {language}\n\t* Description:\n{description}\n"
|
1022
|
+
f"* Usage: {usage}\n")
|
1023
|
+
|
1024
|
+
if object_action == 'Update':
|
1025
|
+
guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
|
1026
|
+
glossary_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
|
1027
|
+
if not glossary_exists:
|
1028
|
+
msg = f"Glossary can't be updated; `{glossary_name}` not found"
|
1029
|
+
print_msg("ERROR", msg, debug_level)
|
1030
|
+
valid = False
|
1031
|
+
else:
|
1032
|
+
msg = f"Glossary can be updated; `{glossary_name}` found"
|
1033
|
+
print_msg(ALWAYS, msg, debug_level)
|
1034
|
+
|
1035
|
+
|
1036
|
+
elif object_action == "Create":
|
1037
|
+
if glossary_exists:
|
1038
|
+
msg = f"Glossary `{glossary_name}` can't be created because it already exists.\n"
|
1039
|
+
print_msg("ERROR", msg, debug_level)
|
1040
|
+
valid = False
|
1041
|
+
elif valid:
|
1042
|
+
msg = f"It is valid to create Glossary `{glossary_name}` with:\n"
|
1043
|
+
print_msg("ALWAYS", msg, debug_level)
|
1044
|
+
|
1045
|
+
if directive == "display":
|
1046
|
+
print(Markdown(glossary_display))
|
1047
|
+
return None
|
1048
|
+
|
1049
|
+
elif directive == "validate":
|
1050
|
+
if valid:
|
1051
|
+
print(Markdown(glossary_display))
|
1052
|
+
else:
|
1053
|
+
msg = f"Validation failed for Glossary `{glossary_name}`\n"
|
1054
|
+
print_msg(ERROR, msg, debug_level)
|
1055
|
+
print(Markdown(glossary_display))
|
1056
|
+
|
1057
|
+
return valid
|
1058
|
+
|
1059
|
+
elif directive == "process":
|
1060
|
+
if valid:
|
1061
|
+
print(Markdown(glossary_display))
|
1062
|
+
else:
|
1063
|
+
if glossary_exists and object_action == "Create":
|
1064
|
+
msg = f"Create failed because glossary `{glossary_name}` exists - changing `Create` to `Update` in processed output \n"
|
1065
|
+
print_msg(ERROR, msg, debug_level)
|
1066
|
+
print(Markdown(glossary_display))
|
1067
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1068
|
+
else:
|
1069
|
+
return None
|
1070
|
+
if object_action == "Update":
|
1071
|
+
if not glossary_exists:
|
1072
|
+
print(f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
|
1073
|
+
f"object_action\n")
|
1074
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1075
|
+
|
1076
|
+
body = {
|
1077
|
+
"class": "ReferenceableRequestBody", "elementProperties": {
|
1078
|
+
"class": "GlossaryProperties", "qualifiedName": known_q_name, "description": description,
|
1079
|
+
"language": language, "usage": usage
|
1080
|
+
}
|
1081
|
+
}
|
1082
|
+
egeria_client.update_glossary(known_guid, body)
|
1083
|
+
print_msg(ALWAYS, f"Updated Glossary `{glossary_name}` with GUID {known_guid}", debug_level)
|
1084
|
+
update_element_dictionary(known_q_name, {
|
1085
|
+
'guid': known_guid, 'display_name': glossary_name
|
1086
|
+
})
|
1087
|
+
return egeria_client.get_glossary_by_guid(known_guid, output_format='MD')
|
1088
|
+
elif object_action == "Create":
|
1089
|
+
glossary_guid = None
|
1090
|
+
|
1091
|
+
if glossary_exists:
|
1092
|
+
print(f"\nGlossary `{glossary_name}` already exists and result document updated\n")
|
1093
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1094
|
+
else:
|
1095
|
+
glossary_guid = egeria_client.create_glossary(glossary_name, description, language, usage)
|
1096
|
+
glossary = egeria_client.get_glossary_by_guid(glossary_guid)
|
1097
|
+
if glossary == NO_GLOSSARIES_FOUND:
|
1098
|
+
print(f"{ERROR}Just created with GUID {glossary_guid} but Glossary not found\n")
|
1099
|
+
return None
|
1100
|
+
qualified_name = glossary['glossaryProperties']["qualifiedName"]
|
1101
|
+
update_element_dictionary(qualified_name, {
|
1102
|
+
'guid': glossary_guid, 'display_name': glossary_name
|
1103
|
+
})
|
1104
|
+
# return update_a_command(txt, object_action, object_type, qualified_name, glossary_guid)
|
1105
|
+
print_msg(ALWAYS, f"Created Glossary `{glossary_name}` with GUID {glossary_guid}", debug_level)
|
1106
|
+
return egeria_client.get_glossary_by_guid(glossary_guid, output_format='FORM')
|
1107
|
+
else:
|
1108
|
+
return None
|
1109
|
+
else:
|
1110
|
+
return None
|
1111
|
+
|
1112
|
+
|
1113
|
+
def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1114
|
+
"""
|
1115
|
+
Processes a glossary category create or update object_action by extracting key attributes such as
|
1116
|
+
category name, qualified, description, and anchor glossary from the given txt..
|
1117
|
+
|
1118
|
+
:param txt: A string representing the input cell to be processed for
|
1119
|
+
extracting category-related attributes.
|
1120
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1121
|
+
:return: A string summarizing the outcome of the processing.
|
1122
|
+
"""
|
1123
|
+
valid = True
|
1124
|
+
set_debug_level(directive)
|
1125
|
+
|
1126
|
+
command, object_type, object_action = extract_command_plus(txt)
|
1127
|
+
|
1128
|
+
category_name = process_simple_attribute(txt, ['Category Name', 'category_name', 'Cat'])
|
1129
|
+
print(Markdown(f"{pre_command} `{command}` for category: `\'{category_name}\'` with directive: `{directive}` "))
|
1130
|
+
|
1131
|
+
owning_glossary_name = extract_attribute(txt, ['Owning Glossary', 'In Glossary'])
|
1132
|
+
description = process_simple_attribute(txt, ['Description'])
|
1133
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'])
|
1134
|
+
|
1135
|
+
parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS, "INFO")
|
1136
|
+
|
1137
|
+
element_labels = CATEGORY_NAME_LABELS
|
1138
|
+
element_labels.append('Display Name')
|
1139
|
+
# Check if category exists (and get qname and guid)
|
1140
|
+
if category_name is None:
|
1141
|
+
valid = False
|
1142
|
+
known_q_name, known_guid, category_exists = None
|
1143
|
+
else:
|
1144
|
+
element_labels = CATEGORY_NAME_LABELS
|
1145
|
+
element_labels.append('Display Name')
|
1146
|
+
known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type,
|
1147
|
+
element_labels, txt,
|
1148
|
+
object_action, None)
|
1149
|
+
|
1150
|
+
# Check if owning glossary exists (and get qname)
|
1151
|
+
if owning_glossary_name is None:
|
1152
|
+
valid = False
|
1153
|
+
known_glossary_q_name, known_glossary__guid, glossary_exists = None
|
1154
|
+
|
1155
|
+
else:
|
1156
|
+
known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(
|
1157
|
+
egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
|
1158
|
+
|
1159
|
+
if parent_category_name:
|
1160
|
+
_, parent_guid, parent_valid, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
|
1161
|
+
parent_category_name)
|
1162
|
+
else:
|
1163
|
+
parent_guid = None
|
1164
|
+
parent_exists = False
|
1165
|
+
parent_valid = False
|
1166
|
+
|
1167
|
+
category_display = (
|
1168
|
+
f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_name}\n\t"
|
1169
|
+
f"* Description:\n{description}\n\t* Parent Category: {parent_category_name}\n\t"
|
1170
|
+
f"* Qualified Name: {q_name}\n\t")
|
1171
|
+
|
1172
|
+
if object_action == 'Update':
|
1173
|
+
guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
|
1174
|
+
|
1175
|
+
category_display += (f"* GUID: {guid}\n\n")
|
1176
|
+
if not category_exists:
|
1177
|
+
msg = f"Category {category_name} can't be updated; {category_name} not found."
|
1178
|
+
print_msg(ERROR, msg, debug_level)
|
1179
|
+
valid = False
|
1180
|
+
else:
|
1181
|
+
msg = f"Glossary can be updated; {category_name} found"
|
1182
|
+
print_msg(ALWAYS, msg, debug_level)
|
1183
|
+
|
1184
|
+
elif object_action == "Create":
|
1185
|
+
if category_exists:
|
1186
|
+
msg = f"Category {category_name} can't be created because it already exists.\n"
|
1187
|
+
print_msg("ERROR", msg, debug_level)
|
1188
|
+
valid = False
|
1189
|
+
elif valid:
|
1190
|
+
msg = f"It is valid to create Category `{category_name}` with:\n"
|
1191
|
+
print_msg("ALWAYS", msg, debug_level)
|
1192
|
+
|
1193
|
+
if directive == "display":
|
1194
|
+
print(Markdown(category_display))
|
1195
|
+
return None
|
1196
|
+
|
1197
|
+
elif directive == "validate":
|
1198
|
+
if valid:
|
1199
|
+
print(Markdown(category_display))
|
1200
|
+
else:
|
1201
|
+
msg = f"Validation failed for {object_type} `{category_name}`\n"
|
1202
|
+
print_msg(ERROR, msg, debug_level)
|
1203
|
+
print(Markdown(category_display))
|
1204
|
+
return valid
|
1205
|
+
|
1206
|
+
elif directive == "process":
|
1207
|
+
if valid:
|
1208
|
+
print(Markdown(category_display))
|
1209
|
+
else:
|
1210
|
+
if category_exists and object_action == "Create":
|
1211
|
+
msg = f"Create failed because category `{category_name}` exists - changing `Create` to `Update` in processed output \n"
|
1212
|
+
print_msg(ERROR, msg, debug_level)
|
1213
|
+
print(Markdown(category_display))
|
1214
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1215
|
+
else:
|
1216
|
+
return None
|
1217
|
+
|
1218
|
+
if object_action == "Update":
|
1219
|
+
if not category_exists:
|
1220
|
+
print(f"\n{ERROR}category `{category_name}` does not exist! Updating result document with Create "
|
1221
|
+
f"object_action\n")
|
1222
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1223
|
+
|
1224
|
+
# Update the basic category properties
|
1225
|
+
egeria_client.update_category(known_guid, category_name, description, known_q_name, None)
|
1226
|
+
msg = f"->Updated category `{category_name}`with GUID {known_guid}"
|
1227
|
+
print_msg(ALWAYS, msg, debug_level)
|
1228
|
+
|
1229
|
+
# Update parent-child relationships
|
1230
|
+
|
1231
|
+
update_element_dictionary(known_q_name, {
|
1232
|
+
'guid': known_guid, 'display_name': category_name
|
1233
|
+
})
|
1234
|
+
|
1235
|
+
category_sync = update_category_parent(egeria_client, known_guid, parent_category_name)
|
1236
|
+
print_msg(ALWAYS, f"Updated Category hierarchy for `{category_name}` with outcome {category_sync}",
|
1237
|
+
debug_level)
|
1238
|
+
return egeria_client.get_category_by_guid(known_guid, output_format='FORM')
|
1239
|
+
|
1240
|
+
elif object_action == "Create":
|
1241
|
+
is_root = True
|
1242
|
+
|
1243
|
+
if category_exists:
|
1244
|
+
msg = (f"Cannot create`{category_name}` because it already exists; result document written for "
|
1245
|
+
f"category update\n")
|
1246
|
+
print_msg(WARNING, msg, debug_level)
|
1247
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1248
|
+
else:
|
1249
|
+
category_guid = egeria_client.create_category(known_glossary_guid, category_name, description, is_root)
|
1250
|
+
category_details = egeria_client.get_category_by_guid(category_guid)
|
1251
|
+
|
1252
|
+
if category_details == NO_CATEGORIES_FOUND:
|
1253
|
+
msg = f"Just created category with GUID {category_guid} but category not found"
|
1254
|
+
print_msg(ERROR, msg, debug_level)
|
1255
|
+
return None
|
1256
|
+
|
1257
|
+
qualified_name = category_details['glossaryCategoryProperties']["qualifiedName"]
|
1258
|
+
update_element_dictionary(qualified_name, {
|
1259
|
+
'guid': category_guid, 'display_name': category_name
|
1260
|
+
})
|
1261
|
+
print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
|
1262
|
+
if parent_valid and parent_guid:
|
1263
|
+
egeria_client.set_parent_category(parent_guid, category_guid)
|
1264
|
+
print_msg(ALWAYS, f"Set parent category for `{category_name}` to `{parent_category_name}`",
|
1265
|
+
debug_level)
|
1266
|
+
else:
|
1267
|
+
print_msg(ERROR,
|
1268
|
+
f"Parent category `{parent_category_name}` not found or invalid for `{category_name}`",
|
1269
|
+
debug_level)
|
1270
|
+
return egeria_client.get_category_by_guid(category_guid, output_format='FORM')
|
1271
|
+
return None
|
1272
|
+
return None
|
1273
|
+
|
1274
|
+
|
1275
|
+
def update_category_parent(egeria_client, category_guid: str, parent_category_name: str = None) -> bool:
|
1276
|
+
"""
|
1277
|
+
Updates the parent relationship for a category.
|
1278
|
+
|
1279
|
+
If a parent category is specified, it will check if a parent is currently set.
|
1280
|
+
If a parent category was set and is the same as the parent category specified, no change is needed.
|
1281
|
+
If a parent category was set and is different from the parent_category_name, the parent category is updated.
|
1282
|
+
If parent_category_name is None or empty and an existing parent category was set, the parent category is removed.
|
1283
|
+
|
1284
|
+
Parameters
|
1285
|
+
----------
|
1286
|
+
egeria_client: EgeriaTech
|
1287
|
+
The Egeria client to use for API calls
|
1288
|
+
category_guid: str
|
1289
|
+
The GUID of the category to update
|
1290
|
+
parent_category_name: str, optional
|
1291
|
+
The name of the parent category to set, or None to remove the parent
|
1292
|
+
|
1293
|
+
Returns
|
1294
|
+
-------
|
1295
|
+
|
1296
|
+
True if successful, False otherwise.
|
1297
|
+
|
1298
|
+
"""
|
1299
|
+
outcome = True
|
1300
|
+
# Handle parent category updates
|
1301
|
+
if parent_category_name:
|
1302
|
+
# Check if a parent is currently set
|
1303
|
+
current_parent = egeria_client.get_category_parent(category_guid)
|
1304
|
+
|
1305
|
+
if isinstance(current_parent, str) and "No Parent Category found" in current_parent:
|
1306
|
+
# No parent currently set, need to set it
|
1307
|
+
_, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
|
1308
|
+
parent_category_name)
|
1309
|
+
|
1310
|
+
if parent_exists and parent_guid:
|
1311
|
+
egeria_client.set_parent_category(parent_guid, category_guid)
|
1312
|
+
print_msg(ALWAYS, f"Set parent category of category to `{parent_category_name}`", debug_level)
|
1313
|
+
else:
|
1314
|
+
print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
|
1315
|
+
outcome = False
|
1316
|
+
else:
|
1317
|
+
# Parent is set, check if it's the same
|
1318
|
+
current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
|
1319
|
+
|
1320
|
+
if current_parent_name != parent_category_name:
|
1321
|
+
# Different parent, need to update
|
1322
|
+
# First remove the current parent
|
1323
|
+
current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
|
1324
|
+
if current_parent_guid:
|
1325
|
+
egeria_client.remove_parent_category(current_parent_guid, category_guid)
|
1326
|
+
|
1327
|
+
# Then set the new parent
|
1328
|
+
_, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
|
1329
|
+
parent_category_name)
|
1330
|
+
|
1331
|
+
if parent_exists and parent_guid:
|
1332
|
+
egeria_client.set_parent_category(parent_guid, category_guid)
|
1333
|
+
print_msg(ALWAYS,
|
1334
|
+
f"Updated parent category from `{current_parent_name}` to `{parent_category_name}`",
|
1335
|
+
debug_level)
|
1336
|
+
else:
|
1337
|
+
print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
|
1338
|
+
outcome = False
|
1339
|
+
elif parent_category_name is None or parent_category_name == '':
|
1340
|
+
# Check if a parent is currently set and remove it if needed
|
1341
|
+
current_parent = egeria_client.get_category_parent(category_guid)
|
1342
|
+
|
1343
|
+
if not isinstance(current_parent, str) or "No Parent Category found" not in current_parent:
|
1344
|
+
# Parent is set, need to remove it
|
1345
|
+
current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
|
1346
|
+
current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
|
1347
|
+
|
1348
|
+
if current_parent_guid:
|
1349
|
+
egeria_client.remove_parent_category(current_parent_guid, category_guid)
|
1350
|
+
print_msg(ALWAYS, f"Removed parent category `{current_parent_name}`", debug_level)
|
1351
|
+
|
1352
|
+
return outcome
|
1353
|
+
|
1354
|
+
|
1355
|
+
def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1356
|
+
"""
|
1357
|
+
Processes a term create or update object_action by extracting key attributes such as
|
1358
|
+
term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
|
1359
|
+
|
1360
|
+
:param txt: A string representing the input cell to be processed for
|
1361
|
+
extracting glossary-related attributes.
|
1362
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1363
|
+
:return: A string summarizing the outcome of the processing.
|
1364
|
+
"""
|
1365
|
+
valid = True
|
1366
|
+
categories_list = None
|
1367
|
+
cats_exist = False
|
1368
|
+
set_debug_level(directive)
|
1369
|
+
known_q_name = None
|
1370
|
+
command = extract_command(txt)
|
1371
|
+
object_type = command.split(' ')[1].strip()
|
1372
|
+
object_action = command.split(' ')[0].strip()
|
1373
|
+
|
1374
|
+
term_name = process_simple_attribute(txt, ['Term Name', 'Display Name'], ERROR)
|
1375
|
+
print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
|
1376
|
+
summary = process_simple_attribute(txt, ['Summary'],INFO)
|
1377
|
+
description = process_simple_attribute(txt, ['Description'], INFO)
|
1378
|
+
abbreviation = process_simple_attribute(txt, ['Abbreviation'], INFO)
|
1379
|
+
examples = process_simple_attribute(txt, ['Examples'], INFO)
|
1380
|
+
usage = process_simple_attribute(txt, ['Usage'], INFO)
|
1381
|
+
status = process_simple_attribute(txt, ['Status'])
|
1382
|
+
status = status.upper() if status else 'DRAFT'
|
1383
|
+
version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"], INFO)
|
1384
|
+
q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
|
1385
|
+
|
1386
|
+
aliases = process_simple_attribute(txt, ['Aliases','Alias'], INFO)
|
1387
|
+
if aliases:
|
1388
|
+
alias_list = list(filter(None, re.split(r'[,\n]+', aliases.strip())))
|
1389
|
+
else:
|
1390
|
+
alias_list = None
|
1391
|
+
|
1392
|
+
|
1393
|
+
|
1394
|
+
# validate term name and get existing qualified_name and guid if they exist
|
1395
|
+
if term_name is None:
|
1396
|
+
valid = False
|
1397
|
+
known_q_name, known_guid, term_exists = None
|
1398
|
+
else:
|
1399
|
+
element_labels = TERM_NAME_LABELS
|
1400
|
+
element_labels.append('Display Name')
|
1401
|
+
known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
|
1402
|
+
element_labels, txt, object_action,
|
1403
|
+
version)
|
1404
|
+
|
1405
|
+
# get the glossary qualified name this term is in
|
1406
|
+
glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
|
1407
|
+
if glossary_name is None:
|
1408
|
+
valid = False
|
1409
|
+
known_glossary_guid = None
|
1410
|
+
known_glossary_q_name = None
|
1411
|
+
glossary_valid = False
|
1412
|
+
glossary_exists = False
|
1413
|
+
else:
|
1414
|
+
known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
|
1415
|
+
egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
|
1416
|
+
|
1417
|
+
# process categories, if present
|
1418
|
+
categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
|
1419
|
+
if categories: # Find information about categoriess that classify this term
|
1420
|
+
msg = "Checking for categories that classify this term"
|
1421
|
+
print_msg("DEBUG-INFO", msg, debug_level)
|
1422
|
+
categories_list, cat_q_name_list, cats_valid, cats_exist = process_name_list(egeria_client, 'Glossary Categories',
|
1423
|
+
txt, CATEGORY_NAME_LABELS)
|
1424
|
+
if cats_exist and cats_valid:
|
1425
|
+
msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
|
1426
|
+
print_msg("INFO", msg, debug_level)
|
1427
|
+
else:
|
1428
|
+
msg = "No valid glossary categories found."
|
1429
|
+
print_msg("INFO", msg, debug_level)
|
1430
|
+
else:
|
1431
|
+
cats_exist = cats_valid = False
|
1432
|
+
cat_q_name_list = None
|
1433
|
+
|
1434
|
+
if object_action == "Update": # check to see if provided information exists and is consistent with existing info
|
1435
|
+
term_guid = process_simple_attribute(txt, GUID_LABELS)
|
1436
|
+
update_description = process_simple_attribute(txt, ['Update Description'])
|
1437
|
+
term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
|
1438
|
+
f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t"
|
1439
|
+
f"* Categories: {categories}\n\t"
|
1440
|
+
f"* Summary: {summary}\n\t* Description: {description}\n\t"
|
1441
|
+
f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
|
1442
|
+
f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}"
|
1443
|
+
f"\n\t* Update Description: {update_description}\n")
|
1444
|
+
if not term_exists:
|
1445
|
+
msg = f"Update request invalid, Term {term_name} does not exist\n"
|
1446
|
+
print_msg(ERROR, msg, debug_level)
|
1447
|
+
valid = False
|
1448
|
+
|
1449
|
+
elif object_action == 'Create': # if the object_action is create, check that it doesn't already exist
|
1450
|
+
term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
|
1451
|
+
f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
|
1452
|
+
f"* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t* Description: {description}\n\t"
|
1453
|
+
f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
|
1454
|
+
f"* Version: {version}\n\t* Status: {status}\n")
|
1455
|
+
if term_exists:
|
1456
|
+
msg = f"Term `{term_name}` cannot be created since it already exists\n"
|
1457
|
+
print_msg(ERROR, msg, debug_level)
|
1458
|
+
else:
|
1459
|
+
msg = f"It is valid to create Term `{term_name}`"
|
1460
|
+
print_msg(ALWAYS, msg, debug_level)
|
1461
|
+
|
1462
|
+
if directive == "display":
|
1463
|
+
print(Markdown(term_display))
|
1464
|
+
return None
|
1465
|
+
elif directive == "validate":
|
1466
|
+
print(Markdown(term_display))
|
1467
|
+
return valid
|
1468
|
+
elif directive == "process":
|
1469
|
+
try:
|
1470
|
+
if not valid: # First validate the term before we process it
|
1471
|
+
if term_exists and object_action == "Create":
|
1472
|
+
msg = f"Create failed because term `{term_name}` exists - changing `Create` to `Update` in processed output \n"
|
1473
|
+
print_msg(ERROR, msg, debug_level)
|
1474
|
+
print(Markdown(term_display))
|
1475
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1476
|
+
else:
|
1477
|
+
return None
|
1478
|
+
|
1479
|
+
print(Markdown(term_display))
|
1480
|
+
if object_action == "Update" and directive == "process":
|
1481
|
+
if not term_exists:
|
1482
|
+
return None
|
1483
|
+
body = {
|
1484
|
+
"class": "ReferenceableRequestBody", "elementProperties": { "displayName": term_name,
|
1485
|
+
"class": "GlossaryTermProperties", "qualifiedName": known_q_name, "aliases": alias_list, "summary": summary,
|
1486
|
+
"description": description, "abbreviation": abbreviation, "examples": examples, "usage": usage,
|
1487
|
+
"publishVersionIdentifier": version, "status": status
|
1488
|
+
}, "updateDescription": update_description
|
1489
|
+
}
|
1490
|
+
egeria_client.update_term(known_guid, body_slimmer(body), is_merge_update=False)
|
1491
|
+
# if cat_exist and cat_valid:
|
1492
|
+
update_term_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
|
1493
|
+
print_msg(ALWAYS,
|
1494
|
+
f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
|
1495
|
+
debug_level)
|
1496
|
+
return egeria_client.get_term_by_guid(known_guid,
|
1497
|
+
'md') # return update_a_command(txt, object_action, object_type,
|
1498
|
+
# known_q_name, known_guid)
|
1499
|
+
elif object_action == "Update" and directive == "validate": # is sthis reachable?
|
1500
|
+
return egeria_client.get_term_by_guid(known_guid, 'md')
|
1501
|
+
|
1502
|
+
elif object_action == "Create":
|
1503
|
+
if term_exists:
|
1504
|
+
msg = f"Term {term_name} exists so result document modifies term create to term update"
|
1505
|
+
print_msg(INFO, msg, debug_level)
|
1506
|
+
return update_a_command(txt, command, object_type, q_name, known_guid)
|
1507
|
+
else:
|
1508
|
+
## get the guid for the glossary from the name - first look in cache
|
1509
|
+
cached = get_element_dictionary().get(known_glossary_q_name, None)
|
1510
|
+
|
1511
|
+
if cached is not None:
|
1512
|
+
glossary_guid = cached.get('guid', None)
|
1513
|
+
if glossary_guid is None:
|
1514
|
+
msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
|
1515
|
+
print_msg(WARNING, msg, debug_level) # should this ever occur?
|
1516
|
+
return None
|
1517
|
+
else:
|
1518
|
+
glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
|
1519
|
+
if glossary_guid == NO_ELEMENTS_FOUND:
|
1520
|
+
msg = f"Glossary {known_glossary_q_name} not found"
|
1521
|
+
print_msg(WARNING, msg, debug_level)
|
1522
|
+
return None
|
1523
|
+
term_body = {
|
1524
|
+
"class": "ReferenceableRequestBody", "elementProperties": {
|
1525
|
+
"class": "GlossaryTermProperties", "qualifiedName": known_q_name, "displayName": term_name,
|
1526
|
+
"aliases": alias_list, "summary": summary, "description": description, "abbreviation": abbreviation,
|
1527
|
+
"examples": examples, "usage": usage, "publishVersionIdentifier": version
|
1528
|
+
# "additionalProperties":
|
1529
|
+
# {
|
1530
|
+
# "propertyName1": "xxxx",
|
1531
|
+
# "propertyName2": "xxxx"
|
1532
|
+
# }
|
1533
|
+
}, "initialStatus": status
|
1534
|
+
}
|
1535
|
+
term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, body_slimmer(term_body))
|
1536
|
+
if term_guid == NO_ELEMENTS_FOUND:
|
1537
|
+
print(f"{ERROR}Term {term_name} not created")
|
1538
|
+
return None
|
1539
|
+
if cats_exist and categories is not None:
|
1540
|
+
update_term_categories(egeria_client, term_guid, cats_exist, cat_q_name_list)
|
1541
|
+
update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
|
1542
|
+
print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
|
1543
|
+
return egeria_client.get_term_by_guid(term_guid,
|
1544
|
+
'MD') # return update_a_command(txt, object_action,
|
1545
|
+
# object_type, q_name, term_guid)
|
1546
|
+
except Exception as e:
|
1547
|
+
print(f"{ERROR}Error creating term {term_name}: {e}")
|
1548
|
+
console.print_exception(show_locals=True)
|
1549
|
+
return None
|
1550
|
+
else:
|
1551
|
+
return None
|
1552
|
+
|
1553
|
+
|
1554
|
+
|
1555
|
+
|
1556
|
+
def process_create_term_term_relationship_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1557
|
+
""" Relate two terms through the specified relationship. ."""
|
1558
|
+
set_debug_level(directive)
|
1559
|
+
valid = True
|
1560
|
+
command = extract_command(txt)
|
1561
|
+
object_type = command.split(' ')[1].strip()
|
1562
|
+
object_action = command.split(' ')[0].strip()
|
1563
|
+
term1_guid = None
|
1564
|
+
term2_guid = None
|
1565
|
+
|
1566
|
+
|
1567
|
+
term_relationship = process_simple_attribute(txt, ["Term Relationship", "Relationship Type"], "ERROR")
|
1568
|
+
if term_relationship not in TERM_RELATIONSHPS:
|
1569
|
+
valid = False
|
1570
|
+
|
1571
|
+
print(Markdown(f"{pre_command} `{command}` for term relationship: `{term_relationship}` with directive: `{directive}` "))
|
1572
|
+
|
1573
|
+
term1_q_name, term1_guid, term1_valid, term1_exists = process_element_identifiers(egeria_client, object_type, ["Term 1 Name", "Term 1"], txt,
|
1574
|
+
"Exists Required", None )
|
1575
|
+
|
1576
|
+
term2_q_name, term2_guid, term2_valid, term2_exists = process_element_identifiers(egeria_client, object_type, ["Term 2 Name", "Term 2"], txt,
|
1577
|
+
"Exists Required", None )
|
1578
|
+
|
1579
|
+
request_display = (f"\n\t* Term 1 Qualified Name: {term1_q_name}\n\t* Term 2 Qualified Name {term2_q_name}\n\t"
|
1580
|
+
f"* Term Relationship: {term_relationship}")
|
1581
|
+
|
1582
|
+
if not(term1_valid and term2_valid and term1_exists and term2_exists):
|
1583
|
+
valid = False
|
1584
|
+
|
1585
|
+
if directive == "display":
|
1586
|
+
print(request_display)
|
1587
|
+
return None
|
1588
|
+
elif directive == "validate":
|
1589
|
+
print(request_display)
|
1590
|
+
return str(valid)
|
1591
|
+
elif directive == "process":
|
1592
|
+
try:
|
1593
|
+
print(request_display)
|
1594
|
+
if not valid: # First validate the term before we process it
|
1595
|
+
return None
|
1596
|
+
egeria_client.add_relationship_between_terms(term1_guid, term2_guid, term_relationship)
|
1597
|
+
print_msg(ALWAYS, f"Relationship `{term_relationship}` created", debug_level)
|
1598
|
+
update_md = (f"\n\n# Update Term-Term Relationship\n\n## Term 1 Name:\n\n{term1_q_name}"
|
1599
|
+
f"\n\n## Term 2 Name\n\n{term2_q_name}\n\n## Term Relationship:\n\n{term_relationship}")
|
1600
|
+
return update_md
|
1601
|
+
|
1602
|
+
|
1603
|
+
except Exception as e:
|
1604
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
1605
|
+
console.print_exception(show_locals=True)
|
1606
|
+
return None
|
1607
|
+
else:
|
1608
|
+
return None
|
1609
|
+
|
1610
|
+
|
1611
|
+
def process_per_proj_upsert_command(egeria_client: ProjectManager, txt: str, directive: str = "display") -> str | None:
|
1612
|
+
"""
|
1613
|
+
Processes a personal project create or update object_action by extracting key attributes such as
|
1614
|
+
glossary name, language, description, and usage from the given cell.
|
1615
|
+
|
1616
|
+
:param txt: A string representing the input cell to be processed for
|
1617
|
+
extracting glossary-related attributes.
|
1618
|
+
:param directive: an optional string indicating the directive to be used - display, validate or execute
|
1619
|
+
:return: A string summarizing the outcome of the processing.
|
1620
|
+
"""
|
1621
|
+
command = extract_command(txt)
|
1622
|
+
object = command.split()
|
1623
|
+
object_type = f"{object[1]} {object[2]}"
|
1624
|
+
object_action = object[0]
|
1625
|
+
set_debug_level(directive)
|
1626
|
+
|
1627
|
+
project_name = process_simple_attribute(txt, ['Project Name'])
|
1628
|
+
description = process_simple_attribute(txt, ['Description'])
|
1629
|
+
project_identifier = process_simple_attribute(txt, ['Project Identifier'])
|
1630
|
+
project_status = process_simple_attribute(txt, ['Project Status'])
|
1631
|
+
project_phase = process_simple_attribute(txt, ['Project Phase'])
|
1632
|
+
project_health = process_simple_attribute(txt, ['Project Health'])
|
1633
|
+
start_date = process_simple_attribute(txt, ['Start Date'])
|
1634
|
+
planned_end_date = process_simple_attribute(txt, ['Planned End Date'])
|
1635
|
+
print(Markdown(f"{pre_command} `\'{command}\'` for project: `{project_name}` with directive: `{directive}` "))
|
1636
|
+
|
1637
|
+
project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
|
1638
|
+
f"* Status: {project_status}\n\t* Description: {description}\n\t"
|
1639
|
+
f"* Phase: {project_phase}\n\t* Health: {project_health}\n\t"
|
1640
|
+
f"* Start Date: {start_date}\n\t* Planned End Date: {planned_end_date}\n")
|
1641
|
+
|
1642
|
+
def validate_project(obj_action: str) -> tuple[bool, bool, str, str]:
|
1643
|
+
valid = True
|
1644
|
+
msg = ""
|
1645
|
+
known_guid = None
|
1646
|
+
known_q_name = None
|
1647
|
+
|
1648
|
+
project_details = egeria_client.get_projects_by_name(project_name)
|
1649
|
+
if project_details == NO_PROJECTS_FOUND:
|
1650
|
+
project_exists = False
|
1651
|
+
else:
|
1652
|
+
project_exists = True
|
1653
|
+
|
1654
|
+
if project_name is None:
|
1655
|
+
msg = f"* {ERROR}Project name is missing\n"
|
1656
|
+
valid = False
|
1657
|
+
if project_status is None:
|
1658
|
+
msg += f"* {INFO}No Project status found\n"
|
1659
|
+
|
1660
|
+
if description is None:
|
1661
|
+
msg += f"* {INFO}No Description found\n"
|
1662
|
+
|
1663
|
+
if project_identifier is None:
|
1664
|
+
msg += f"* {INFO}No Project Identifier found\n"
|
1665
|
+
|
1666
|
+
if project_phase is None:
|
1667
|
+
msg += f"* {INFO}No Project Phase found\n"
|
1668
|
+
|
1669
|
+
if project_health is None:
|
1670
|
+
msg += f"* {INFO}No Project Health found\n"
|
1671
|
+
|
1672
|
+
if start_date is None:
|
1673
|
+
msg += f"* {INFO}No Start Date found\n"
|
1674
|
+
elif not is_valid_iso_date(start_date):
|
1675
|
+
msg += f"* {ERROR}Start Date is not a valid ISO date of form YYYY-MM-DD\n"
|
1676
|
+
valid = False
|
1677
|
+
|
1678
|
+
if planned_end_date is None:
|
1679
|
+
msg += f"* {INFO} No Planned End Date found\n"
|
1680
|
+
elif not is_valid_iso_date(planned_end_date):
|
1681
|
+
msg += f"* {ERROR}Planned End Date is not a valid ISO date of form YYYY-MM-DD\n"
|
1682
|
+
valid = False
|
1683
|
+
|
1684
|
+
if obj_action == "Update":
|
1685
|
+
q_name = process_simple_attribute(txt, 'Qualified Name')
|
1686
|
+
|
1687
|
+
if not project_exists:
|
1688
|
+
msg += f"* {ERROR}Project {project_name} does not exist\n"
|
1689
|
+
valid = False
|
1690
|
+
if len(project_details) > 1 and project_exists:
|
1691
|
+
msg += f"* {ERROR}More than one project with name {project_name} found\n"
|
1692
|
+
valid = False
|
1693
|
+
if len(project_details) == 1:
|
1694
|
+
known_guid = project_details[0]['elementHeader'].get('guid', None)
|
1695
|
+
known_q_name = project_details[0]['glossaryProperties'].get('qualifiedName', None)
|
1696
|
+
if q_name is None:
|
1697
|
+
msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
|
1698
|
+
valid = True
|
1699
|
+
elif q_name != known_q_name:
|
1700
|
+
msg += (f"* {ERROR}Project {project_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
|
1701
|
+
valid = False
|
1702
|
+
if valid:
|
1703
|
+
msg += project_display
|
1704
|
+
msg += f"* -->Project {project_name} exists and can be updated\n"
|
1705
|
+
else:
|
1706
|
+
msg += f"* --> validation failed\n"
|
1707
|
+
msg += '---'
|
1708
|
+
print(Markdown(msg))
|
1709
|
+
return valid, project_exists, known_guid, known_q_name
|
1710
|
+
|
1711
|
+
elif obj_action == "Create":
|
1712
|
+
if project_exists:
|
1713
|
+
msg += f"\n{ERROR}Project {project_name} already exists"
|
1714
|
+
else:
|
1715
|
+
msg += f"\n-->It is valid to create Project \'{project_name}\' with:\n"
|
1716
|
+
print(Markdown(msg))
|
1717
|
+
return valid, project_exists, known_guid, known_q_name
|
1718
|
+
|
1719
|
+
if directive == "display":
|
1720
|
+
print(Markdown(project_display))
|
1721
|
+
return None
|
1722
|
+
|
1723
|
+
elif directive == "validate":
|
1724
|
+
is_valid, exists, known_guid, known_q_name = validate_project(object_action)
|
1725
|
+
valid = is_valid if is_valid else None
|
1726
|
+
return valid
|
1727
|
+
|
1728
|
+
elif directive == "process":
|
1729
|
+
is_valid, exists, known_guid, known_q_name = validate_project(object_action)
|
1730
|
+
if not is_valid:
|
1731
|
+
return None
|
1732
|
+
if object_action == "Update":
|
1733
|
+
if not exists:
|
1734
|
+
print(f"\n\n-->Project {project_name} does not exist")
|
1735
|
+
return None
|
1736
|
+
|
1737
|
+
egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name, description,
|
1738
|
+
project_status, project_phase, project_health, start_date, planned_end_date,
|
1739
|
+
False)
|
1740
|
+
print_msg(ALWAYS, f"Updated Project `{project_name}` with GUID {known_guid}", debug_level)
|
1741
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1742
|
+
elif object_action == "Create":
|
1743
|
+
guid = None
|
1744
|
+
if exists:
|
1745
|
+
print(f"Project `{project_name}` already exists and update document created")
|
1746
|
+
return update_a_command(txt, command, object_type, known_q_name, known_guid)
|
1747
|
+
else:
|
1748
|
+
guid = egeria_client.create_project(None, None, None, False, project_name, description,
|
1749
|
+
"PersonalProject", project_identifier, True, project_status,
|
1750
|
+
project_phase, project_health, start_date, planned_end_date)
|
1751
|
+
project_g = egeria_client.get_project_by_guid(guid)
|
1752
|
+
if project_g == NO_GLOSSARIES_FOUND:
|
1753
|
+
print(f"Just created with GUID {guid} but Project not found")
|
1754
|
+
return None
|
1755
|
+
|
1756
|
+
q_name = project_g['projectProperties']["qualifiedName"]
|
1757
|
+
update_element_dictionary(q_name, {'guid': guid, 'display_name': project_name})
|
1758
|
+
print_msg(ALWAYS, f"Created project `{project_name}` with GUID {guid}", debug_level)
|
1759
|
+
return update_a_command(txt, command, object_type, q_name, guid)
|
1760
|
+
|
1761
|
+
|
1762
|
+
def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1763
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
1764
|
+
set_debug_level(directive)
|
1765
|
+
valid = True
|
1766
|
+
command = extract_command(txt)
|
1767
|
+
|
1768
|
+
search_string = process_simple_attribute(txt, SEARCH_LABELS)
|
1769
|
+
if search_string is None:
|
1770
|
+
search_string = '*'
|
1771
|
+
print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
|
1772
|
+
|
1773
|
+
glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary', "Glossary Name"])
|
1774
|
+
if glossary is not None:
|
1775
|
+
_, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
|
1776
|
+
msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
|
1777
|
+
print_msg(INFO, msg, debug_level)
|
1778
|
+
else:
|
1779
|
+
glossary_guid = None
|
1780
|
+
msg = f"No glossary found"
|
1781
|
+
print_msg(INFO, msg, debug_level)
|
1782
|
+
|
1783
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS)
|
1784
|
+
if output_format is None:
|
1785
|
+
output_format = "LIST"
|
1786
|
+
elif output_format not in ELEMENT_OUTPUT_FORMATS:
|
1787
|
+
valid = False
|
1788
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
1789
|
+
|
1790
|
+
request_display = (f"\n\t* Search String: {search_string}\n\t* Glossary: {glossary}\n\t* Output Format: "
|
1791
|
+
f"{output_format}\n")
|
1792
|
+
|
1793
|
+
if directive == "display":
|
1794
|
+
print(Markdown(request_display))
|
1795
|
+
return None
|
1796
|
+
elif directive == "validate":
|
1797
|
+
print(Markdown(request_display))
|
1798
|
+
return valid
|
1799
|
+
elif directive == "process":
|
1800
|
+
try:
|
1801
|
+
print(Markdown(request_display))
|
1802
|
+
if not valid: # First validate the term before we process it
|
1803
|
+
return None
|
1804
|
+
|
1805
|
+
term_list_md = f"\n# Term List for search string: `{search_string}`\n\n"
|
1806
|
+
if output_format == "DICT":
|
1807
|
+
struct = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
|
1808
|
+
term_list_md += f"```{json.dumps(struct, indent=4)}```\n"
|
1809
|
+
else:
|
1810
|
+
term_list_md += egeria_client.find_glossary_terms(search_string, glossary_guid,
|
1811
|
+
output_format=output_format)
|
1812
|
+
print_msg("ALWAYS", f"Wrote Term List for search string: `{search_string}`", debug_level)
|
1813
|
+
|
1814
|
+
return term_list_md
|
1815
|
+
|
1816
|
+
md_table = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
|
1817
|
+
|
1818
|
+
print_msg("ALWAYS", f"Wrote Term list for search string `{search_string}`", debug_level)
|
1819
|
+
return md_table
|
1820
|
+
|
1821
|
+
except Exception as e:
|
1822
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
1823
|
+
console.print_exception(show_locals=True)
|
1824
|
+
return None
|
1825
|
+
else:
|
1826
|
+
return None
|
1827
|
+
|
1828
|
+
|
1829
|
+
def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1830
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
1831
|
+
set_debug_level(directive)
|
1832
|
+
valid = True
|
1833
|
+
command = extract_command(txt)
|
1834
|
+
|
1835
|
+
search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
|
1836
|
+
if search_string is None:
|
1837
|
+
search_string = '*'
|
1838
|
+
print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
|
1839
|
+
|
1840
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
|
1841
|
+
if output_format is None:
|
1842
|
+
output_format = "LIST"
|
1843
|
+
elif output_format not in ELEMENT_OUTPUT_FORMATS:
|
1844
|
+
valid = False
|
1845
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
1846
|
+
|
1847
|
+
request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
|
1848
|
+
|
1849
|
+
if directive == "display":
|
1850
|
+
print(Markdown(request_display))
|
1851
|
+
return None
|
1852
|
+
elif directive == "validate":
|
1853
|
+
print(Markdown(request_display))
|
1854
|
+
return valid
|
1855
|
+
elif directive == "process":
|
1856
|
+
try:
|
1857
|
+
print(Markdown(request_display))
|
1858
|
+
if not valid: # First validate the term before we process it
|
1859
|
+
return None
|
1860
|
+
|
1861
|
+
cat_list_md = f"\n# Category List for search string: `{search_string}`\n\n"
|
1862
|
+
if output_format == "DICT":
|
1863
|
+
struct = egeria_client.find_glossary_categories(search_string, output_format=output_format)
|
1864
|
+
cat_list_md += f"```{json.dumps(struct, indent=4)}```\n"
|
1865
|
+
else:
|
1866
|
+
cat_list_md += egeria_client.find_glossary_categories(search_string, output_format=output_format)
|
1867
|
+
print_msg("ALWAYS", f"Wrote Category List for search string: `{search_string}`", debug_level)
|
1868
|
+
|
1869
|
+
return cat_list_md
|
1870
|
+
|
1871
|
+
except Exception as e:
|
1872
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
1873
|
+
console.print_exception(show_locals=True)
|
1874
|
+
return None
|
1875
|
+
else:
|
1876
|
+
|
1877
|
+
return None
|
1878
|
+
|
1879
|
+
|
1880
|
+
def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1881
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
1882
|
+
set_debug_level(directive)
|
1883
|
+
valid = True
|
1884
|
+
command = extract_command(txt)
|
1885
|
+
|
1886
|
+
known_glossary_guid = ""
|
1887
|
+
|
1888
|
+
glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, "ERROR")
|
1889
|
+
|
1890
|
+
_, known_glossary_guid, valid, _ = process_element_identifiers(egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt,
|
1891
|
+
EXISTS_REQUIRED, None)
|
1892
|
+
|
1893
|
+
print(Markdown(f"{pre_command} `{command}` for glossary:`{glossary_name}` with directive: `{directive}`"))
|
1894
|
+
|
1895
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
|
1896
|
+
if output_format is None:
|
1897
|
+
output_format = "MD"
|
1898
|
+
elif output_format not in ["DICT", "LIST", "MD"]:
|
1899
|
+
valid = False
|
1900
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
1901
|
+
|
1902
|
+
request_display = f"\n\t* Glossary name: {glossary_name}\n\t* Output Format: {output_format}\n"
|
1903
|
+
|
1904
|
+
if directive == "display":
|
1905
|
+
print(Markdown(request_display))
|
1906
|
+
return None
|
1907
|
+
elif directive == "validate":
|
1908
|
+
print(Markdown(request_display))
|
1909
|
+
return str(valid)
|
1910
|
+
elif directive == "process":
|
1911
|
+
try:
|
1912
|
+
print(Markdown(request_display))
|
1913
|
+
if not valid: # First validate the term before we process it
|
1914
|
+
return None
|
1915
|
+
|
1916
|
+
glossary_structure_md = f"\n# Glossary Structure for `{glossary_name}`\n\n"
|
1917
|
+
if output_format == "DICT":
|
1918
|
+
struct = egeria_client.get_glossary_category_structure(known_glossary_guid, output_format=output_format)
|
1919
|
+
glossary_structure_md += f"```{json.dumps(struct, indent=4)}```\n"
|
1920
|
+
else:
|
1921
|
+
glossary_structure_md += egeria_client.get_glossary_category_structure(known_glossary_guid,
|
1922
|
+
output_format=output_format)
|
1923
|
+
print_msg("ALWAYS", f"Wrote Glossary Structure for glossary: `{glossary_name}`", debug_level)
|
1924
|
+
|
1925
|
+
return glossary_structure_md
|
1926
|
+
|
1927
|
+
except Exception as e:
|
1928
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
1929
|
+
console.print_exception(show_locals=True)
|
1930
|
+
return None
|
1931
|
+
else:
|
1932
|
+
return None
|
1933
|
+
|
1934
|
+
|
1935
|
+
def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1936
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
1937
|
+
set_debug_level(directive)
|
1938
|
+
valid = True
|
1939
|
+
command = extract_command(txt)
|
1940
|
+
|
1941
|
+
search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
|
1942
|
+
if search_string is None:
|
1943
|
+
search_string = '*'
|
1944
|
+
print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
|
1945
|
+
if search_string is None:
|
1946
|
+
search_string = '*'
|
1947
|
+
|
1948
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
|
1949
|
+
if output_format is None:
|
1950
|
+
output_format = "LIST"
|
1951
|
+
elif output_format not in ELEMENT_OUTPUT_FORMATS:
|
1952
|
+
valid = False
|
1953
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
1954
|
+
|
1955
|
+
request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
|
1956
|
+
|
1957
|
+
if directive == "display":
|
1958
|
+
print(request_display)
|
1959
|
+
return None
|
1960
|
+
elif directive == "validate":
|
1961
|
+
print(request_display)
|
1962
|
+
return valid
|
1963
|
+
elif directive == "process":
|
1964
|
+
try:
|
1965
|
+
print(request_display)
|
1966
|
+
if not valid: # First validate the term before we process it
|
1967
|
+
return None
|
1968
|
+
|
1969
|
+
glossary_list_md = f"\n# Glossary List for `{search_string}`\n\n"
|
1970
|
+
if output_format == "DICT":
|
1971
|
+
struct = egeria_client.find_glossaries(search_string, output_format=output_format)
|
1972
|
+
glossary_list_md += f"```{json.dumps(struct, indent=4)}```\n"
|
1973
|
+
else:
|
1974
|
+
glossary_list_md += egeria_client.find_glossaries(search_string, output_format=output_format)
|
1975
|
+
print_msg("ALWAYS", f"Wrote Glossary List for search string: `{search_string}`", debug_level)
|
1976
|
+
|
1977
|
+
return glossary_list_md
|
1978
|
+
|
1979
|
+
except Exception as e:
|
1980
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
1981
|
+
console.print_exception(show_locals=True)
|
1982
|
+
return None
|
1983
|
+
else:
|
1984
|
+
return None
|
1985
|
+
|
1986
|
+
|
1987
|
+
def process_term_details_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
1988
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
1989
|
+
set_debug_level(directive)
|
1990
|
+
valid = True
|
1991
|
+
command = extract_command(txt)
|
1992
|
+
object_type = command.split(' ')[1].strip()
|
1993
|
+
object_action = command.split(' ')[0].strip()
|
1994
|
+
|
1995
|
+
|
1996
|
+
term_identifier = process_simple_attribute(txt, TERM_NAME_LABELS, "ERROR")
|
1997
|
+
|
1998
|
+
print(Markdown(f"{pre_command} `{command}` for term:`{term_identifier}` with directive: `{directive}`"))
|
1999
|
+
|
2000
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
|
2001
|
+
if output_format is None:
|
2002
|
+
output_format = "REPORT"
|
2003
|
+
else:
|
2004
|
+
output_format = output_format.upper()
|
2005
|
+
|
2006
|
+
if output_format not in ["DICT", "REPORT"]:
|
2007
|
+
valid = False
|
2008
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
2009
|
+
|
2010
|
+
request_display = f"\n\t* Term Identifier: {term_identifier}\n\t* Output Format {output_format}"
|
2011
|
+
|
2012
|
+
if directive == "display":
|
2013
|
+
print(request_display)
|
2014
|
+
return None
|
2015
|
+
elif directive == "validate":
|
2016
|
+
print(request_display)
|
2017
|
+
return valid
|
2018
|
+
elif directive == "process":
|
2019
|
+
try:
|
2020
|
+
print(request_display)
|
2021
|
+
if not valid: # First validate the term before we process it
|
2022
|
+
return None
|
2023
|
+
output = egeria_client.get_term_details(term_identifier, output_format=output_format)
|
2024
|
+
if output_format == "DICT":
|
2025
|
+
output = f"```{json.dumps(output, indent=4)}```"
|
2026
|
+
print_msg("ALWAYS", f"Wrote Term Details for term: `{term_identifier}`", debug_level)
|
2027
|
+
|
2028
|
+
return output
|
2029
|
+
|
2030
|
+
except Exception as e:
|
2031
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
2032
|
+
console.print_exception(show_locals=True)
|
2033
|
+
return None
|
2034
|
+
else:
|
2035
|
+
return None
|
2036
|
+
|
2037
|
+
|
2038
|
+
|
2039
|
+
def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
2040
|
+
""" List terms as a markdown table. Filter based on optional search string. """
|
2041
|
+
set_debug_level(directive)
|
2042
|
+
valid = True
|
2043
|
+
command = extract_command(txt)
|
2044
|
+
object_type = command.split(' ')[1].strip()
|
2045
|
+
object_action = command.split(' ')[0].strip()
|
2046
|
+
|
2047
|
+
element_labels = TERM_NAME_LABELS
|
2048
|
+
element_labels.append('Display Name')
|
2049
|
+
|
2050
|
+
term_name = process_simple_attribute(txt, element_labels, "ERROR")
|
2051
|
+
|
2052
|
+
known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
|
2053
|
+
element_labels, txt, object_action, )
|
2054
|
+
|
2055
|
+
print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
|
2056
|
+
|
2057
|
+
output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
|
2058
|
+
if output_format is None:
|
2059
|
+
output_format = "LIST"
|
2060
|
+
elif output_format not in ["DICT", "LIST"]:
|
2061
|
+
valid = False
|
2062
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
2063
|
+
|
2064
|
+
request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format {output_format}\n\t* GUID: {known_guid}\n"
|
2065
|
+
|
2066
|
+
if directive == "display":
|
2067
|
+
print(request_display)
|
2068
|
+
return None
|
2069
|
+
elif directive == "validate":
|
2070
|
+
print(request_display)
|
2071
|
+
return valid
|
2072
|
+
elif directive == "process":
|
2073
|
+
try:
|
2074
|
+
print(request_display)
|
2075
|
+
if not valid: # First validate the term before we process it
|
2076
|
+
return None
|
2077
|
+
term_history_md = f"\n# Term History for `{term_name}`\n\n"
|
2078
|
+
if output_format == "DICT":
|
2079
|
+
struct = egeria_client.list_term_revision_history(known_guid, output_format=output_format)
|
2080
|
+
term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
|
2081
|
+
else:
|
2082
|
+
term_history_md += egeria_client.list_full_term_history(known_guid, output_format)
|
2083
|
+
print_msg("ALWAYS", f"Wrote Term History for term `{term_name}`", debug_level)
|
2084
|
+
|
2085
|
+
return term_history_md
|
2086
|
+
|
2087
|
+
except Exception as e:
|
2088
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
2089
|
+
console.print_exception(show_locals=True)
|
2090
|
+
return None
|
2091
|
+
else:
|
2092
|
+
return None
|
2093
|
+
|
2094
|
+
|
2095
|
+
def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
2096
|
+
""" List term revision history as a markdown table or list."""
|
2097
|
+
set_debug_level(directive)
|
2098
|
+
valid = True
|
2099
|
+
command = extract_command(txt)
|
2100
|
+
object_type = command.split(' ')[1].strip()
|
2101
|
+
object_action = command.split(' ')[0].strip()
|
2102
|
+
known_q_name = None
|
2103
|
+
known_guid = None
|
2104
|
+
|
2105
|
+
element_labels = TERM_NAME_LABELS
|
2106
|
+
|
2107
|
+
term_name = process_simple_attribute(txt, element_labels, "ERROR")
|
2108
|
+
print(Markdown(f"{pre_command} `{command}` for term: `{term_name}` with directive: `{directive}` "))
|
2109
|
+
|
2110
|
+
known_q_name, known_guid, valid, _ = process_element_identifiers(egeria_client, object_type, element_labels, txt,
|
2111
|
+
object_action, )
|
2112
|
+
output_format = process_simple_attribute(txt, ['Output Format', 'Format'], 'INFO')
|
2113
|
+
if output_format is None:
|
2114
|
+
output_format = "LIST"
|
2115
|
+
elif output_format not in ["DICT", "LIST", "MD"]:
|
2116
|
+
valid = False
|
2117
|
+
print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
|
2118
|
+
|
2119
|
+
request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format: {output_format}\n"
|
2120
|
+
|
2121
|
+
if directive == "display":
|
2122
|
+
print(request_display)
|
2123
|
+
return None
|
2124
|
+
elif directive == "validate":
|
2125
|
+
print(request_display)
|
2126
|
+
return str(valid)
|
2127
|
+
elif directive == "process":
|
2128
|
+
try:
|
2129
|
+
print(request_display)
|
2130
|
+
if not valid: # First validate the term before we process it
|
2131
|
+
return None
|
2132
|
+
term_history_md = f"\n# Term Revision History for `{term_name}`\n\n"
|
2133
|
+
if output_format == "DICT":
|
2134
|
+
struct = egeria_client.list_term_revision_history(known_guid, output_format)
|
2135
|
+
term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
|
2136
|
+
else:
|
2137
|
+
term_history_md += egeria_client.list_term_revision_history(known_guid, output_format)
|
2138
|
+
print_msg("ALWAYS", f"Wrote Term Revision History for term `{term_name}`", debug_level)
|
2139
|
+
return term_history_md
|
2140
|
+
|
2141
|
+
except Exception as e:
|
2142
|
+
print(f"{ERROR}Error performing {command}: {e}")
|
2143
|
+
console.print_exception(show_locals=True)
|
2144
|
+
return None
|
2145
|
+
else:
|
2146
|
+
return None
|
2147
|
+
|