pyegeria 5.3.9.9.3__py3-none-any.whl → 5.5.3.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.

Potentially problematic release.


This version of pyegeria might be problematic. Click here for more details.

Files changed (272) hide show
  1. commands/__init__.py +24 -0
  2. commands/cat/Dr-Egeria_md-orig.py +2 -2
  3. commands/cat/__init__.py +1 -17
  4. commands/cat/collection_actions.py +197 -0
  5. commands/cat/dr_egeria_command_help.py +372 -0
  6. commands/cat/dr_egeria_jupyter.py +7 -7
  7. commands/cat/dr_egeria_md.py +27 -182
  8. commands/cat/exp_list_glossaries.py +11 -14
  9. commands/cat/get_asset_graph.py +37 -267
  10. commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
  11. commands/cat/get_project_dependencies.py +14 -14
  12. commands/cat/get_project_structure.py +15 -14
  13. commands/cat/get_tech_type_elements.py +16 -116
  14. commands/cat/glossary_actions.py +145 -298
  15. commands/cat/list_assets.py +3 -11
  16. commands/cat/list_cert_types.py +17 -63
  17. commands/cat/list_collections.py +46 -138
  18. commands/cat/list_deployed_catalogs.py +15 -27
  19. commands/cat/list_deployed_database_schemas.py +27 -43
  20. commands/cat/list_deployed_databases.py +16 -31
  21. commands/cat/list_deployed_servers.py +35 -54
  22. commands/cat/list_glossaries.py +18 -17
  23. commands/cat/list_projects.py +10 -12
  24. commands/cat/list_tech_type_elements.py +21 -37
  25. commands/cat/list_tech_types.py +13 -25
  26. commands/cat/list_terms.py +38 -79
  27. commands/cat/list_todos.py +4 -11
  28. commands/cat/list_user_ids.py +3 -10
  29. commands/cat/my_reports.py +559 -0
  30. commands/cat/run_report.py +394 -0
  31. commands/cat/run_report_orig.py +528 -0
  32. commands/cli/egeria.py +222 -247
  33. commands/cli/egeria_cat.py +68 -81
  34. commands/cli/egeria_my.py +13 -0
  35. commands/cli/egeria_ops.py +69 -74
  36. commands/cli/egeria_tech.py +17 -93
  37. commands/cli/ops_config.py +3 -6
  38. commands/{cat/list_categories.py → deprecated/list_data_designer.py} +53 -64
  39. commands/{cat/list_data_structures.py → deprecated/list_data_structures_full.py} +3 -6
  40. commands/deprecated/old_get_asset_graph.py +315 -0
  41. commands/my/__init__.py +0 -2
  42. commands/my/list_my_profile.py +27 -34
  43. commands/my/list_my_roles.py +1 -7
  44. commands/my/monitor_my_todos.py +1 -7
  45. commands/my/monitor_open_todos.py +6 -7
  46. commands/my/todo_actions.py +4 -5
  47. commands/ops/__init__.py +0 -2
  48. commands/ops/gov_server_actions.py +17 -21
  49. commands/ops/list_archives.py +17 -38
  50. commands/ops/list_catalog_targets.py +33 -40
  51. commands/ops/load_archive.py +35 -26
  52. commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
  53. commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
  54. commands/ops/monitor_engine_activity.py +79 -77
  55. commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
  56. commands/ops/monitor_platform_status.py +38 -50
  57. commands/ops/monitor_server_startup.py +6 -11
  58. commands/ops/monitor_server_status.py +7 -11
  59. commands/ops/orig_monitor_server_list.py +8 -8
  60. commands/ops/orig_monitor_server_status.py +1 -5
  61. commands/ops/refresh_integration_daemon.py +5 -5
  62. commands/ops/restart_integration_daemon.py +5 -5
  63. commands/ops/table_integ_daemon_status.py +6 -6
  64. commands/ops/x_engine_actions.py +7 -7
  65. commands/tech/__init__.py +0 -2
  66. commands/tech/{generic_actions.py → element_actions.py} +6 -11
  67. commands/tech/get_element_info.py +20 -29
  68. commands/tech/get_guid_info.py +23 -42
  69. commands/tech/get_tech_details.py +20 -35
  70. commands/tech/get_tech_type_template.py +28 -39
  71. commands/tech/list_all_om_type_elements.py +24 -30
  72. commands/tech/list_all_om_type_elements_x.py +22 -28
  73. commands/tech/list_all_related_elements.py +19 -28
  74. commands/tech/list_anchored_elements.py +22 -30
  75. commands/tech/list_asset_types.py +19 -24
  76. commands/tech/list_elements_by_classification_by_property_value.py +26 -32
  77. commands/tech/list_elements_by_property_value.py +19 -25
  78. commands/tech/list_elements_by_property_value_x.py +20 -28
  79. commands/tech/list_elements_for_classification.py +28 -41
  80. commands/tech/list_gov_action_processes.py +16 -27
  81. commands/tech/list_information_supply_chains.py +22 -30
  82. commands/tech/list_registered_services.py +14 -26
  83. commands/tech/list_related_elements_with_prop_value.py +15 -25
  84. commands/tech/list_related_specification.py +1 -4
  85. commands/tech/list_relationship_types.py +15 -25
  86. commands/tech/list_relationships.py +20 -36
  87. commands/tech/list_solution_blueprints.py +28 -33
  88. commands/tech/list_solution_components.py +23 -29
  89. commands/tech/list_solution_roles.py +21 -32
  90. commands/tech/list_tech_templates.py +51 -54
  91. commands/tech/list_valid_metadata_values.py +5 -9
  92. commands/tech/table_tech_templates.py +2 -6
  93. commands/tech/x_list_related_elements.py +1 -4
  94. examples/GeoSpatial Products Example.py +524 -0
  95. examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
  96. examples/Jupyter Notebooks/README.md +2 -0
  97. examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
  98. examples/Jupyter Notebooks/common/__init__.py +14 -0
  99. examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
  100. examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
  101. examples/Jupyter Notebooks/common/globals.ipynb +184 -0
  102. examples/Jupyter Notebooks/common/globals.py +154 -0
  103. examples/Jupyter Notebooks/common/orig_globals.py +152 -0
  104. examples/format_sets/all_format_sets.json +910 -0
  105. examples/format_sets/custom_format_sets.json +268 -0
  106. examples/format_sets/subset_format_sets.json +187 -0
  107. examples/format_sets_save_load_example.py +291 -0
  108. examples/jacquard_data_sets.py +129 -0
  109. examples/output_formats_example.py +193 -0
  110. examples/test_jacquard_data_sets.py +54 -0
  111. examples/test_jacquard_data_sets_scenarios.py +94 -0
  112. md_processing/__init__.py +90 -0
  113. md_processing/command_dispatcher.py +33 -0
  114. md_processing/command_mapping.py +221 -0
  115. md_processing/data/commands/commands_data_designer.json +537 -0
  116. md_processing/data/commands/commands_external_reference.json +733 -0
  117. md_processing/data/commands/commands_feedback.json +155 -0
  118. md_processing/data/commands/commands_general.json +204 -0
  119. md_processing/data/commands/commands_glossary.json +218 -0
  120. md_processing/data/commands/commands_governance.json +3678 -0
  121. md_processing/data/commands/commands_product_manager.json +865 -0
  122. md_processing/data/commands/commands_project.json +642 -0
  123. md_processing/data/commands/commands_solution_architect.json +366 -0
  124. md_processing/data/commands.json +17568 -0
  125. md_processing/data/commands_working.json +30641 -0
  126. md_processing/data/gened_report_specs.py +6584 -0
  127. md_processing/data/generated_format_sets.json +6533 -0
  128. md_processing/data/generated_format_sets_old.json +4137 -0
  129. md_processing/data/generated_format_sets_old.py +45 -0
  130. md_processing/dr_egeria.py +182 -0
  131. md_processing/md_commands/__init__.py +3 -0
  132. md_processing/md_commands/data_designer_commands.py +1276 -0
  133. md_processing/md_commands/ext_ref_commands.py +530 -0
  134. md_processing/md_commands/feedback_commands.py +726 -0
  135. md_processing/md_commands/glossary_commands.py +684 -0
  136. md_processing/md_commands/governance_officer_commands.py +600 -0
  137. md_processing/md_commands/product_manager_commands.py +1266 -0
  138. md_processing/md_commands/project_commands.py +383 -0
  139. md_processing/md_commands/solution_architect_commands.py +1184 -0
  140. md_processing/md_commands/view_commands.py +295 -0
  141. md_processing/md_processing_utils/__init__.py +4 -0
  142. md_processing/md_processing_utils/common_md_proc_utils.py +1249 -0
  143. md_processing/md_processing_utils/common_md_utils.py +578 -0
  144. md_processing/md_processing_utils/determine_width.py +103 -0
  145. md_processing/md_processing_utils/extraction_utils.py +547 -0
  146. md_processing/md_processing_utils/gen_report_specs.py +643 -0
  147. md_processing/md_processing_utils/generate_dr_help.py +193 -0
  148. md_processing/md_processing_utils/generate_md_cmd_templates.py +144 -0
  149. md_processing/md_processing_utils/generate_md_templates.py +83 -0
  150. md_processing/md_processing_utils/md_processing_constants.py +1228 -0
  151. md_processing/md_processing_utils/message_constants.py +19 -0
  152. pyegeria/__init__.py +201 -443
  153. pyegeria/core/__init__.py +40 -0
  154. pyegeria/core/_base_platform_client.py +574 -0
  155. pyegeria/core/_base_server_client.py +573 -0
  156. pyegeria/core/_exceptions.py +457 -0
  157. pyegeria/core/_globals.py +60 -0
  158. pyegeria/core/_server_client.py +6073 -0
  159. pyegeria/core/_validators.py +257 -0
  160. pyegeria/core/config.py +654 -0
  161. pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
  162. pyegeria/core/load_config.py +37 -0
  163. pyegeria/core/logging_configuration.py +207 -0
  164. pyegeria/core/mcp_adapter.py +144 -0
  165. pyegeria/core/mcp_server.py +212 -0
  166. pyegeria/core/utils.py +405 -0
  167. pyegeria/deprecated/__init__.py +0 -0
  168. pyegeria/{_client.py → deprecated/_client.py} +62 -24
  169. pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
  170. pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1988 -1878
  171. pyegeria/deprecated/output_formatter_with_machine_keys.py +1127 -0
  172. pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +216 -229
  173. pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
  174. pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
  175. pyegeria/egeria_cat_client.py +25 -51
  176. pyegeria/egeria_client.py +140 -98
  177. pyegeria/egeria_config_client.py +48 -24
  178. pyegeria/egeria_tech_client.py +170 -83
  179. pyegeria/models/__init__.py +150 -0
  180. pyegeria/models/collection_models.py +168 -0
  181. pyegeria/models/models.py +654 -0
  182. pyegeria/omvs/__init__.py +84 -0
  183. pyegeria/omvs/action_author.py +342 -0
  184. pyegeria/omvs/actor_manager.py +5980 -0
  185. pyegeria/omvs/asset_catalog.py +842 -0
  186. pyegeria/omvs/asset_maker.py +2736 -0
  187. pyegeria/omvs/automated_curation.py +4403 -0
  188. pyegeria/omvs/classification_manager.py +11213 -0
  189. pyegeria/omvs/collection_manager.py +5780 -0
  190. pyegeria/omvs/community_matters_omvs.py +468 -0
  191. pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
  192. pyegeria/{data_designer_omvs.py → omvs/data_designer.py} +1991 -1691
  193. pyegeria/omvs/data_discovery.py +869 -0
  194. pyegeria/omvs/data_engineer.py +372 -0
  195. pyegeria/omvs/digital_business.py +1133 -0
  196. pyegeria/omvs/external_links.py +1752 -0
  197. pyegeria/omvs/feedback_manager.py +834 -0
  198. pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
  199. pyegeria/omvs/glossary_manager.py +3231 -0
  200. pyegeria/omvs/governance_officer.py +3009 -0
  201. pyegeria/omvs/lineage_linker.py +314 -0
  202. pyegeria/omvs/location_arena.py +1525 -0
  203. pyegeria/omvs/metadata_expert.py +668 -0
  204. pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
  205. pyegeria/omvs/my_profile.py +1042 -0
  206. pyegeria/omvs/notification_manager.py +358 -0
  207. pyegeria/omvs/people_organizer.py +394 -0
  208. pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
  209. pyegeria/omvs/product_manager.py +1825 -0
  210. pyegeria/omvs/project_manager.py +1907 -0
  211. pyegeria/omvs/reference_data.py +1140 -0
  212. pyegeria/omvs/registered_info.py +334 -0
  213. pyegeria/omvs/runtime_manager.py +2817 -0
  214. pyegeria/omvs/schema_maker.py +446 -0
  215. pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
  216. pyegeria/omvs/solution_architect.py +6490 -0
  217. pyegeria/omvs/specification_properties.py +37 -0
  218. pyegeria/omvs/subject_area.py +1042 -0
  219. pyegeria/omvs/template_manager_omvs.py +236 -0
  220. pyegeria/omvs/time_keeper.py +1761 -0
  221. pyegeria/omvs/valid_metadata.py +3221 -0
  222. pyegeria/omvs/valid_metadata_lists.py +37 -0
  223. pyegeria/omvs/valid_type_lists.py +37 -0
  224. pyegeria/view/__init__.py +28 -0
  225. pyegeria/view/_output_format_models.py +514 -0
  226. pyegeria/view/_output_formats.py +14 -0
  227. pyegeria/view/base_report_formats.py +2719 -0
  228. pyegeria/view/dr_egeria_reports.py +56 -0
  229. pyegeria/view/format_set_executor.py +397 -0
  230. pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
  231. pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
  232. pyegeria/view/output_formatter.py +1297 -0
  233. pyegeria-5.5.3.3.dist-info/METADATA +218 -0
  234. pyegeria-5.5.3.3.dist-info/RECORD +241 -0
  235. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
  236. pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
  237. pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
  238. commands/cat/.DS_Store +0 -0
  239. commands/cat/README.md +0 -16
  240. commands/cli/txt_custom_v2.tcss +0 -19
  241. commands/my/README.md +0 -17
  242. commands/ops/README.md +0 -24
  243. commands/ops/monitor_asset_events.py +0 -108
  244. commands/tech/README.md +0 -24
  245. pyegeria/.DS_Store +0 -0
  246. pyegeria/README.md +0 -35
  247. pyegeria/_globals.py +0 -47
  248. pyegeria/_validators.py +0 -385
  249. pyegeria/asset_catalog_omvs.py +0 -864
  250. pyegeria/automated_curation_omvs.py +0 -3765
  251. pyegeria/collection_manager_omvs.py +0 -2744
  252. pyegeria/dr.egeria spec.md +0 -9
  253. pyegeria/egeria_my_client.py +0 -56
  254. pyegeria/feedback_manager_omvs.py +0 -4573
  255. pyegeria/glossary_browser_omvs.py +0 -3728
  256. pyegeria/glossary_manager_omvs.py +0 -2440
  257. pyegeria/m_test.py +0 -118
  258. pyegeria/md_processing_helpers.py +0 -58
  259. pyegeria/md_processing_utils_orig.py +0 -1103
  260. pyegeria/metadata_explorer_omvs.py +0 -2326
  261. pyegeria/my_profile_omvs.py +0 -1022
  262. pyegeria/output_formatter.py +0 -389
  263. pyegeria/project_manager_omvs.py +0 -1933
  264. pyegeria/registered_info.py +0 -167
  265. pyegeria/solution_architect_omvs.py +0 -2156
  266. pyegeria/template_manager_omvs.py +0 -1414
  267. pyegeria/utils.py +0 -197
  268. pyegeria-5.3.9.9.3.dist-info/METADATA +0 -72
  269. pyegeria-5.3.9.9.3.dist-info/RECORD +0 -143
  270. pyegeria-5.3.9.9.3.dist-info/entry_points.txt +0 -99
  271. /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
  272. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,1266 @@
1
+ """
2
+ This file contains product manager commands for processing Egeria Markdown
3
+ """
4
+ import json
5
+ import os
6
+ from typing import Optional
7
+
8
+ from loguru import logger
9
+ from rich import print
10
+ from rich.console import Console
11
+ from rich.markdown import Markdown
12
+
13
+ from md_processing.md_processing_utils.common_md_proc_utils import (parse_upsert_command, parse_view_command)
14
+ from md_processing.md_processing_utils.common_md_utils import update_element_dictionary, set_update_body, \
15
+ set_element_prop_body, set_delete_request_body, set_rel_request_body, set_create_body, set_object_classifications, \
16
+ set_product_body
17
+ from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, update_a_command)
18
+ from md_processing.md_processing_utils.md_processing_constants import (load_commands)
19
+ from pyegeria import DEBUG_LEVEL, body_slimmer, PyegeriaException, print_basic_exception, print_exception_table
20
+ from pyegeria.egeria_tech_client import EgeriaTech
21
+ from pyegeria.core.utils import make_format_set_name_from_type
22
+
23
+ EGERIA_METADATA_STORE = os.environ.get("EGERIA_METADATA_STORE", "active-metadata-store")
24
+ EGERIA_KAFKA_ENDPOINT = os.environ.get("KAFKA_ENDPOINT", "localhost:9092")
25
+ EGERIA_PLATFORM_URL = os.environ.get("EGERIA_PLATFORM_URL", "https://localhost:9443")
26
+ EGERIA_VIEW_SERVER = os.environ.get("EGERIA_VIEW_SERVER", "view-server")
27
+ EGERIA_VIEW_SERVER_URL = os.environ.get("EGERIA_VIEW_SERVER_URL", "https://localhost:9443")
28
+ EGERIA_INTEGRATION_DAEMON = os.environ.get("EGERIA_INTEGRATION_DAEMON", "integration-daemon")
29
+ EGERIA_INTEGRATION_DAEMON_URL = os.environ.get("EGERIA_INTEGRATION_DAEMON_URL", "https://localhost:9443")
30
+ EGERIA_ADMIN_USER = os.environ.get("ADMIN_USER", "garygeeke")
31
+ EGERIA_ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "secret")
32
+ EGERIA_USER = os.environ.get("EGERIA_USER", "erinoverview")
33
+ EGERIA_USER_PASSWORD = os.environ.get("EGERIA_USER_PASSWORD", "secret")
34
+ EGERIA_WIDTH = os.environ.get("EGERIA_WIDTH", 220)
35
+ EGERIA_JUPYTER = os.environ.get("EGERIA_JUPYTER", False)
36
+ EGERIA_HOME_GLOSSARY_GUID = os.environ.get("EGERIA_HOME_GLOSSARY_GUID", None)
37
+ EGERIA_GLOSSARY_PATH = os.environ.get("EGERIA_GLOSSARY_PATH", None)
38
+ EGERIA_ROOT_PATH = os.environ.get("EGERIA_ROOT_PATH", "../../")
39
+ EGERIA_INBOX_PATH = os.environ.get("EGERIA_INBOX_PATH", "md_processing/dr_egeria_inbox")
40
+ EGERIA_OUTBOX_PATH = os.environ.get("EGERIA_OUTBOX_PATH", "md_processing/dr_egeria_outbox")
41
+ LOCAL_QUALIFIER = os.environ.get("EGERIA_LOCAL_QUALIFIER", None)
42
+
43
+ load_commands('commands.json')
44
+ debug_level = DEBUG_LEVEL
45
+
46
+ console = Console(width=int(200))
47
+
48
+
49
+ #
50
+ # Helper functions for the data designer commands
51
+ #
52
+ @logger.catch
53
+ def add_member_to_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
54
+ guid: str) -> None:
55
+ """
56
+ Add member to data dictionaries and data specifications.
57
+ """
58
+ body = {
59
+ "class": "NewRelationshipRequestBody", "properties": {
60
+ "class": "CollectionMembershipProperties", "membershipRationale": "User Specified",
61
+ "notes": "Added by Dr.Egeria"
62
+ }
63
+ }
64
+ try:
65
+ if collection_list is not None:
66
+ for collection in collection_list:
67
+ egeria_client.add_to_collection(collection, guid, body)
68
+ msg = f"Added `{display_name}` member to `{collection}`"
69
+ logger.info(msg)
70
+ else:
71
+ logger.info("There were no data collections to add.")
72
+ return
73
+
74
+ except Exception as e:
75
+ console.print_exception()
76
+
77
+
78
+ @logger.catch
79
+ def remove_member_from_collections(egeria_client: EgeriaTech, collection_list: list, display_name: str,
80
+ guid: str) -> None:
81
+ try:
82
+ for collection in collection_list:
83
+ egeria_client.remove_from_collection(collection, guid)
84
+ msg = f"Removed `{display_name}` member from `{collection}`"
85
+ logger.info(msg)
86
+ return
87
+
88
+ except Exception as e:
89
+ console.print_exception()
90
+
91
+
92
+ @logger.catch
93
+ def update_data_collection_memberships(egeria_client: EgeriaTech, entity_type: str, guid_list: list,
94
+ collection_class: str, guid: str, display_name: str,
95
+ replace_all_props: bool = True) -> None:
96
+ """ update the collection membership of the element
97
+
98
+ If merge_update is set to True, all existing memberships are removed and new memberships are added.
99
+ If merge_update is set to False, only the new memberships are added.
100
+ """
101
+
102
+ if replace_all_props:
103
+ match entity_type:
104
+ case "Data Specification":
105
+ get_command = egeria_client.get_collection_by_guid
106
+ case "Data Structure":
107
+ get_command = egeria_client.get_data_structure_by_guid
108
+ case "Data Field":
109
+ get_command = egeria_client.get_data_field_by_guid
110
+ case "Data Class":
111
+ get_command = egeria_client.get_data_class_by_guid
112
+
113
+ coll_list = egeria_client.get_data_memberships(get_command, guid)
114
+ if coll_list is None:
115
+ logger.warning("Unexpected -> the collection list was None - assigning empty dict")
116
+ coll_list = {}
117
+ # compare the existing collections to desired collections
118
+ if collection_class == "DataDictionary":
119
+ as_is = set(coll_list.get("DictList", {}))
120
+ elif collection_class == "DataSpec":
121
+ as_is = set(coll_list.get("SpecList", {}))
122
+
123
+ dict_set = set(coll_list.get("DictList", {}))
124
+ spec_set = set(coll_list.get("SpecList", {}))
125
+ to_be_set = set(guid_list) if guid_list is not None else set()
126
+ logger.debug(f"as_is: {as_is}")
127
+ logger.debug(f"to_be_set: {to_be_set}")
128
+
129
+ # Remove membership for collections that are in the as-is but not in the to-be
130
+ to_remove = as_is - to_be_set
131
+ logger.debug(f"to_remove: {to_remove}")
132
+ if len(to_remove) > 0:
133
+ remove_member_from_collections(egeria_client, to_remove, display_name, guid)
134
+
135
+ # add membership for collections that are in the to-be but are not in the as-is
136
+ to_add = to_be_set - as_is
137
+ logger.debug(f"to_add: {to_add}")
138
+ if len(to_add) > 0:
139
+ add_member_to_collections(egeria_client, to_add, display_name, guid)
140
+ else:
141
+ add_member_to_collections(egeria_client, guid_list, display_name, guid)
142
+
143
+
144
+ #
145
+ # Product Manager Commands
146
+ #
147
+
148
+ @logger.catch
149
+ def process_collection_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
150
+ """
151
+ Processes a digital product create or update object_action by extracting key attributes such as
152
+ spec name, parent_guid, parent_relationship_type, parent_at_end_1, category
153
+
154
+ :param txt: A string representing the input cell to be processed for
155
+ extracting glossary-related attributes.
156
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
157
+ :return: A string summarizing the outcome of the processing.
158
+ """
159
+
160
+ command, object_type, object_action = extract_command_plus(txt)
161
+ print(Markdown(f"# {command}\n"))
162
+
163
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
164
+ if not parsed_output:
165
+ logger.error(f"No output for `{object_action}`")
166
+ return None
167
+
168
+ valid = parsed_output['valid']
169
+ exists = parsed_output['exists']
170
+
171
+ qualified_name = parsed_output.get('qualified_name', None)
172
+
173
+ guid = parsed_output.get('guid', None)
174
+
175
+ logger.debug(json.dumps(parsed_output, indent=4))
176
+
177
+ attributes = parsed_output['attributes']
178
+
179
+ display_name = attributes['Display Name'].get('value', None)
180
+ version = attributes['Version Identifier'].get('value', None)
181
+ status = attributes.get('Status', {}).get('value', None)
182
+ output_set = make_format_set_name_from_type(object_type)
183
+ if object_type in ["Root Collection", "Folder"]:
184
+ obj = "Collection"
185
+ if object_type == "Folder":
186
+ qn_prefix = "Folder"
187
+ elif object_type == "Root Collection":
188
+ qn_prefix = "Root"
189
+
190
+ qualified_name = egeria_client.__create_qualified_name__(qn_prefix, display_name, LOCAL_QUALIFIER,
191
+ version_identifier=version)
192
+
193
+ else:
194
+ obj = object_type
195
+ print(Markdown(parsed_output['display']))
196
+
197
+ if directive == "display":
198
+
199
+ return None
200
+ elif directive == "validate":
201
+ if valid:
202
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
203
+ else:
204
+ msg = f"Validation failed for object_action `{command}`\n"
205
+ return valid
206
+
207
+ elif directive == "process":
208
+ try:
209
+
210
+ if object_action == "Update":
211
+ if not exists:
212
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
213
+ f"`{object_action}`\n")
214
+ logger.error(msg)
215
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
216
+ elif not valid:
217
+ return None
218
+ else:
219
+ print(Markdown(
220
+ f"==> Validation of `{command}` completed successfully! Proceeding to apply the changes.\n"))
221
+ prop_body = set_element_prop_body(obj, qualified_name, attributes)
222
+
223
+ body = set_update_body(obj, attributes)
224
+ body['properties'] = set_element_prop_body(obj, qualified_name, attributes)
225
+
226
+ egeria_client.update_collection(guid, body)
227
+ if status:
228
+ egeria_client.update_collection_status(guid, status)
229
+
230
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
231
+ update_element_dictionary(qualified_name, {
232
+ 'guid': guid, 'display_name': display_name
233
+ })
234
+ return egeria_client.get_collection_by_guid(guid, element_type=obj,
235
+ output_format='MD', report_spec=output_set)
236
+
237
+
238
+ elif object_action == "Create":
239
+ if valid is False and exists:
240
+ msg = (f" Digital Product `{display_name}` already exists and result document updated changing "
241
+ f"`Create` to `Update` in processed output\n\n___")
242
+ logger.error(msg)
243
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
244
+
245
+ else:
246
+ body = set_create_body(object_type, attributes)
247
+
248
+ # if this is a root or folder (maybe more in the future), then make sure that the classification is set.
249
+ body["initialClassifications"] = set_object_classifications(object_type, attributes,
250
+ ["Folder", "Root Collection"])
251
+ body["properties"] = set_element_prop_body(obj, qualified_name, attributes)
252
+ parent_guid = body.get('parentGuid', None)
253
+ if parent_guid:
254
+ body['parentRelationshipTypeName'] = "CollectionMembership"
255
+ body['parentAtEnd1'] = True
256
+
257
+ guid = egeria_client.create_collection(body=body)
258
+ if guid:
259
+ update_element_dictionary(qualified_name, {
260
+ 'guid': guid, 'display_name': display_name
261
+ })
262
+ msg = f"\nCreated Element `{display_name}` with GUID {guid}\n\n___"
263
+ # todo - add the source member asset to the product manager
264
+ # create_elem_from_template
265
+ # add this guid to the product collection
266
+ logger.success(msg)
267
+ return egeria_client.get_collection_by_guid(guid, obj, output_format='MD',
268
+ report_spec=output_set)
269
+ else:
270
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
271
+ logger.error(msg)
272
+ return None
273
+
274
+ except PyegeriaException as e:
275
+ logger.error(f"Pyegeria error performing {command}: {e}")
276
+ print_basic_exception(e)
277
+ return None
278
+ except Exception as e:
279
+ logger.error(f"Error performing {command}: {e}")
280
+ else:
281
+ return None
282
+
283
+
284
+ @logger.catch
285
+ def process_digital_product_upsert_command(egeria_client: EgeriaTech, txt: str,
286
+ directive: str = "display") -> Optional[str]:
287
+ """
288
+ Processes a digital product create or update object_action by extracting key attributes such as
289
+ spec name, parent_guid, parent_relationship_type, parent_at_end_1, category
290
+
291
+ :param txt: A string representing the input cell to be processed for
292
+ extracting glossary-related attributes.
293
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
294
+ :return: A string summarizing the outcome of the processing.
295
+ """
296
+
297
+ command, object_type, object_action = extract_command_plus(txt)
298
+ print(Markdown(f"# {command}\n"))
299
+
300
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
301
+
302
+ valid = parsed_output['valid']
303
+ exists = parsed_output['exists']
304
+
305
+ qualified_name = parsed_output.get('qualified_name', None)
306
+ guid = parsed_output.get('guid', None)
307
+
308
+ print(Markdown(parsed_output['display']))
309
+
310
+ logger.debug(json.dumps(parsed_output, indent=4))
311
+
312
+ attributes = parsed_output['attributes']
313
+
314
+ display_name = attributes['Display Name'].get('value', None)
315
+ product_manager = attributes.get('Product Manager', {}).get('value', None)
316
+ product_status = attributes.get('Product Status', {}).get('value', None)
317
+ output_set = make_format_set_name_from_type(object_type)
318
+
319
+ if directive == "display":
320
+
321
+ return None
322
+ elif directive == "validate":
323
+ if valid:
324
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
325
+ else:
326
+ msg = f"Validation failed for object_action `{command}`\n"
327
+ return valid
328
+
329
+ elif directive == "process":
330
+
331
+ try:
332
+ prop_body = set_product_body(object_type, qualified_name, attributes)
333
+
334
+ if object_action == "Update":
335
+ if not exists:
336
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
337
+ f"object_action\n")
338
+ logger.error(msg)
339
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
340
+ elif not valid:
341
+ return None
342
+ else:
343
+ print(Markdown(
344
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
345
+
346
+ body = set_update_body(object_type, attributes)
347
+ body['properties'] = prop_body
348
+ # Todo: Update product manager later?
349
+
350
+ egeria_client.update_digital_product(guid, body)
351
+ # if product_status:
352
+ # egeria_client.update_digital_product_status(guid, product_status)
353
+
354
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
355
+ update_element_dictionary(qualified_name, {
356
+ 'guid': guid, 'display_name': display_name
357
+ })
358
+ return egeria_client.get_collection_by_guid(guid, element_type='Digital Product',
359
+ output_format='MD', report_spec=output_set)
360
+
361
+
362
+ elif object_action == "Create":
363
+ if valid is False and exists:
364
+ msg = (f" Digital Product `{display_name}` already exists and result document updated changing "
365
+ f"`Create` to `Update` in processed output\n\n___")
366
+ logger.error(msg)
367
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
368
+
369
+ else:
370
+ body = set_create_body(object_type, attributes)
371
+ body["initialClassifications"] = set_object_classifications(object_type, attributes, [])
372
+
373
+ body["properties"] = prop_body
374
+
375
+ guid = egeria_client.create_digital_product(body_slimmer(body))
376
+ if guid:
377
+ update_element_dictionary(qualified_name, {
378
+ 'guid': guid, 'display_name': display_name
379
+ })
380
+ # Todo: Add product manager link later? Agreements?
381
+
382
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
383
+ logger.success(msg)
384
+ return egeria_client.get_collection_by_guid(guid, element_type='Digital Product',
385
+ output_format='MD', report_spec=output_set)
386
+ else:
387
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
388
+ logger.error(msg)
389
+ return None
390
+
391
+ except Exception as e:
392
+ logger.error(f"Error performing {command}: {e}")
393
+ return None
394
+ else:
395
+ return None
396
+
397
+ # @logger.catch
398
+ # def process_digital_product_catalog_upsert_command(egeria_client: EgeriaTech, txt: str,
399
+ # directive: str = "display") -> Optional[str]:
400
+ # """
401
+ # Processes a digital product catalog create or update object_action by extracting key attributes such as
402
+ # spec name, parent_guid, parent_relationship_type, parent_at_end_1, category
403
+ #
404
+ # :param txt: A string representing the input cell to be processed for
405
+ # extracting glossary-related attributes.
406
+ # :param directive: an optional string indicating the directive to be used - display, validate or execute
407
+ # :return: A string summarizing the outcome of the processing.
408
+ # """
409
+ #
410
+ # command, object_type, object_action = extract_command_plus(txt)
411
+ # print(Markdown(f"# {command}\n"))
412
+ #
413
+ # parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
414
+ #
415
+ # valid = parsed_output['valid']
416
+ # exists = parsed_output['exists']
417
+ #
418
+ # qualified_name = parsed_output.get('qualified_name', None)
419
+ # guid = parsed_output.get('guid', None)
420
+ #
421
+ # print(Markdown(parsed_output['display']))
422
+ #
423
+ # logger.debug(json.dumps(parsed_output, indent=4))
424
+ #
425
+ # attributes = parsed_output['attributes']
426
+ #
427
+ # display_name = attributes['Display Name'].get('value', None)
428
+ #
429
+ # output_set = make_format_set_name_from_type(object_type)
430
+ #
431
+ # if directive == "display":
432
+ #
433
+ # return None
434
+ # elif directive == "validate":
435
+ # if valid:
436
+ # print(Markdown(f"==> Validation of {command} completed successfully!\n"))
437
+ # else:
438
+ # msg = f"Validation failed for object_action `{command}`\n"
439
+ # return valid
440
+ #
441
+ # elif directive == "process":
442
+ # try:
443
+ # prop_body = set_product_body(object_type, qualified_name, attributes)
444
+ #
445
+ # if object_action == "Update":
446
+ # if not exists:
447
+ # msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
448
+ # f"object_action\n")
449
+ # logger.error(msg)
450
+ # return update_a_command(txt, object_action, object_type, qualified_name, guid)
451
+ # elif not valid:
452
+ # return None
453
+ # else:
454
+ # print(Markdown(
455
+ # f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
456
+ #
457
+ # body = set_update_body(object_type, attributes)
458
+ # body['properties'] = prop_body
459
+ # # Todo: Update product manager later?
460
+ #
461
+ # egeria_client.update_digital_product(guid, body)
462
+ # # if product_status:
463
+ # # egeria_client.update_digital_product_status(guid, product_status)
464
+ #
465
+ # logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
466
+ # update_element_dictionary(qualified_name, {
467
+ # 'guid': guid, 'display_name': display_name
468
+ # })
469
+ # return egeria_client.get_collection_by_guid(guid, element_type='Digital Product',
470
+ # output_format='MD', report_spec=output_set)
471
+ #
472
+ #
473
+ # elif object_action == "Create":
474
+ # if valid is False and exists:
475
+ # msg = (
476
+ # f" Digital Product `{display_name}` already exists and result document updated changing "
477
+ # f"`Create` to `Update` in processed output\n\n___")
478
+ # logger.error(msg)
479
+ # return update_a_command(txt, object_action, object_type, qualified_name, guid)
480
+ #
481
+ # else:
482
+ # body = set_create_body(object_type, attributes)
483
+ # body["initialClassifications"] = set_object_classifications(object_type, attributes, [])
484
+ #
485
+ # body["properties"] = prop_body
486
+ #
487
+ # guid = egeria_client.create_digital_product(body_slimmer(body))
488
+ # if guid:
489
+ # update_element_dictionary(qualified_name, {
490
+ # 'guid': guid, 'display_name': display_name
491
+ # })
492
+ # # Todo: Add product manager link later? Agreements?
493
+ #
494
+ # msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
495
+ # logger.success(msg)
496
+ # return egeria_client.get_collection_by_guid(guid, element_type='Digital Product',
497
+ # output_format='MD',
498
+ # report_spec=output_set)
499
+ # else:
500
+ # msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
501
+ # logger.error(msg)
502
+ # return None
503
+ #
504
+ # except Exception as e:
505
+ # logger.error(f"Error performing {command}: {e}")
506
+ # return None
507
+ # else:
508
+ # return None
509
+
510
+
511
+ @logger.catch
512
+ def process_agreement_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
513
+ """
514
+ Processes an agreement create or update object_action by extracting key attributes such as
515
+ spec name, parent_guid, parent_relationship_type, parent_at_end_1, category
516
+
517
+ :param txt: A string representing the input cell to be processed for
518
+ extracting glossary-related attributes.
519
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
520
+ :return: A string summarizing the outcome of the processing.
521
+ """
522
+ command, object_type, object_action = extract_command_plus(txt)
523
+ print(Markdown(f"# {command}\n"))
524
+
525
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
526
+ if not parsed_output:
527
+ logger.error(f"No output for `{object_action}`")
528
+ return None
529
+
530
+ valid = parsed_output['valid']
531
+ exists = parsed_output['exists']
532
+
533
+ qualified_name = parsed_output.get('qualified_name', None)
534
+ guid = parsed_output.get('guid', None)
535
+
536
+ print(Markdown(parsed_output['display']))
537
+
538
+ logger.debug(json.dumps(parsed_output, indent=4))
539
+
540
+ attributes = parsed_output['attributes']
541
+
542
+ display_name = attributes['Display Name'].get('value', None)
543
+ status = attributes.get('Status', {}).get('value', None)
544
+ output_set = make_format_set_name_from_type(object_type)
545
+
546
+ if directive == "display":
547
+
548
+ return None
549
+ elif directive == "validate":
550
+ if valid:
551
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
552
+ else:
553
+ msg = f"Validation failed for object_action `{command}`\n"
554
+ return valid
555
+
556
+ elif directive == "process":
557
+ try:
558
+ if object_type in ["Data Sharing Agreement"]:
559
+ obj = "Agreement"
560
+ else:
561
+ obj = object_type
562
+
563
+ if object_action == "Update":
564
+ if not exists:
565
+ msg = (f" Element `{display_name}` does not exist! Updating result document with Create "
566
+ f"object_action\n")
567
+ logger.error(msg)
568
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
569
+ elif not valid:
570
+ return None
571
+ else:
572
+ print(Markdown(
573
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
574
+ prop_body = set_element_prop_body(obj, qualified_name, attributes)
575
+
576
+ body = set_update_body(object_type, attributes)
577
+ body['properties'] = set_element_prop_body(object_type, qualified_name, attributes)
578
+
579
+ egeria_client.update_agreement(guid, body)
580
+ # if status is not None and status !={}:
581
+ # egeria_client.update_agreement_status(guid, status)
582
+
583
+ logger.success(f"Updated {object_type} `{display_name}` with GUID {guid}\n\n___")
584
+ update_element_dictionary(qualified_name, {
585
+ 'guid': guid, 'display_name': display_name
586
+ })
587
+ return egeria_client.get_collection_by_guid(guid, element_type='Data Specification',
588
+ output_format='MD', report_spec=output_set)
589
+
590
+
591
+ elif object_action == "Create":
592
+ if valid is False and exists:
593
+ msg = (f" Digital Product `{display_name}` already exists and result document updated changing "
594
+ f"`Create` to `Update` in processed output\n\n___")
595
+ logger.error(msg)
596
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
597
+
598
+ else:
599
+ body = set_create_body(object_type, attributes)
600
+
601
+ # if this is a root or folder (maybe more in the future), then make sure that the classification is set.
602
+ body["initialClassifications"] = set_object_classifications(object_type, attributes,
603
+ ["Data Sharing Agreement"])
604
+ body["properties"] = set_element_prop_body(obj, qualified_name, attributes)
605
+
606
+ guid = egeria_client.create_agreement(body=body)
607
+ if guid:
608
+ update_element_dictionary(qualified_name, {
609
+ 'guid': guid, 'display_name': display_name
610
+ })
611
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
612
+ logger.success(msg)
613
+ return egeria_client.get_collection_by_guid(guid, obj, output_format='MD',
614
+ report_spec=output_set)
615
+ else:
616
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
617
+ logger.error(msg)
618
+ return None
619
+
620
+ except PyegeriaException as e:
621
+ logger.error(f"Pyegeria error performing {command}: {e}")
622
+ print_exception_table(e)
623
+ return None
624
+ except Exception as e:
625
+ logger.error(f"Error performing {command}: {e}")
626
+ else:
627
+ return None
628
+
629
+
630
+ @logger.catch
631
+ def process_csv_element_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
632
+ str]:
633
+ """
634
+ Processes a create CSV element command by extracting key attributes and calling the pyegeria
635
+ api that creates a csv element from template.
636
+
637
+ :param txt: A string representing the input cell to be processed for
638
+ extracting glossary-related attributes.
639
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
640
+ :return: A string summarizing the outcome of the processing.
641
+ """
642
+ command, object_type, object_action = extract_command_plus(txt)
643
+ print(Markdown(f"# {command}\n"))
644
+
645
+ parsed_output = parse_upsert_command(egeria_client, object_type, object_action, txt, directive)
646
+ if not parsed_output:
647
+ logger.error(f"No output for `{object_action}`")
648
+ return None
649
+
650
+ valid = parsed_output['valid']
651
+ exists = parsed_output['exists']
652
+
653
+ qualified_name = parsed_output.get('qualified_name', None)
654
+ guid = parsed_output.get('guid', None)
655
+
656
+ print(Markdown(parsed_output['display']))
657
+
658
+ logger.debug(json.dumps(parsed_output, indent=4))
659
+
660
+ attributes = parsed_output['attributes']
661
+
662
+ display_name = attributes['Display Name'].get('value', None)
663
+ status = attributes.get('Status', {}).get('value', None)
664
+ output_set = make_format_set_name_from_type(object_type)
665
+
666
+ file_name = attributes.get('File Name', {}).get('value', None)
667
+ file_type = attributes.get('File Type', {}).get('value', None)
668
+ file_path = attributes.get('File Path', {}).get('value', None)
669
+ file_encoding = attributes.get('File Encoding', {}).get('value', 'UTF-8')
670
+ file_extension = attributes.get('File Extension', {}).get('value', 'csv')
671
+ file_system_name = attributes.get('File System Name', {}).get('value', None)
672
+ version_identifier = attributes.get('Version Identifier', {}).get('value', None)
673
+ description = attributes.get('Description', {}).get('value', None)
674
+
675
+ if directive == "display":
676
+
677
+ return None
678
+ elif directive == "validate":
679
+ if valid:
680
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
681
+ else:
682
+ msg = f"Validation failed for object_action `{command}`\n"
683
+ return valid
684
+
685
+ elif directive == "process":
686
+ try:
687
+
688
+ if object_action == "Create":
689
+ if valid is False and exists:
690
+ msg = (f" Element `{display_name}` already exists and result document updated changing "
691
+ f"`Create` to `Update` in processed output\n\n___")
692
+ logger.error(msg)
693
+ return update_a_command(txt, object_action, object_type, qualified_name, guid)
694
+
695
+ else:
696
+ guid = egeria_client.get_create_csv_data_file_element_from_template(
697
+ file_name, file_type, file_path, version_identifier, file_encoding, file_extension,
698
+ file_system_name, description)
699
+
700
+ if guid:
701
+ update_element_dictionary(qualified_name, {
702
+ 'guid': guid, 'display_name': display_name
703
+ })
704
+ msg = f"Created Element `{display_name}` with GUID {guid}\n\n___"
705
+ logger.success(msg)
706
+ output_md = (f"# Create CSV File\n\n## Display Name:\n\n {display_name}\n\n"
707
+ f"## File Type:\n\n {file_type}\n\n## File Path:\n\n {file_path}\n\n"
708
+ f"## File Encoding:\n\n {file_encoding}\n\n## File Extension:\n\n {file_extension}\n\n"
709
+ f"## File System Name:\n\n {file_system_name}\n\n## Version Identifier:\n\n {version_identifier}\n\n"
710
+ f"## Description:\n\n {description}\n\n"
711
+ f"## Qualified Name\n\n {qualified_name}\n\n"
712
+ f"## GUID:\n\n {guid}\n\n"
713
+ )
714
+ return output_md
715
+ else:
716
+ msg = f"Failed to create element `{display_name}` with GUID {guid}\n\n___"
717
+ logger.error(msg)
718
+ return None
719
+ else:
720
+ logger.error(f"Currently only the Create action is supported for this command: {command}")
721
+
722
+ except PyegeriaException as e:
723
+ logger.error(f"Pyegeria error performing {command}: {e}")
724
+ print_exception_table(e)
725
+ return None
726
+ except Exception as e:
727
+ logger.error(f"Error performing {command}: {e}")
728
+ else:
729
+ logger.error(f"Invalid directive `{directive}`")
730
+ return None
731
+
732
+
733
+ def process_link_agreement_item_command(egeria_client: EgeriaTech, txt: str,
734
+ directive: str = "display") -> Optional[str]:
735
+ """
736
+ Processes a link or unlink command to add or remove an agreement item.
737
+
738
+ :param txt: A string representing the input cell to be processed for
739
+ extracting blueprint-related attributes.
740
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
741
+ :return: A string summarizing the outcome of the processing.
742
+ """
743
+ command, object_type, object_action = extract_command_plus(txt)
744
+ print(Markdown(f"# {command}\n"))
745
+
746
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
747
+
748
+ print(Markdown(parsed_output['display']))
749
+
750
+ logger.debug(json.dumps(parsed_output, indent=4))
751
+
752
+ attributes = parsed_output['attributes']
753
+ agreement = attributes.get('Agreement Name', {}).get('value', None)
754
+ agreement_guid = attributes.get('Agreement Name', {}).get('guid', None)
755
+ item = attributes.get('Item Name', {}).get('value', None)
756
+ item_guid = attributes.get('Item Name', {}).get('guid', None)
757
+ label = attributes.get('Link Label', {}).get('value', None)
758
+ description = attributes.get('Description', {}).get('value', None)
759
+
760
+ valid = parsed_output['valid']
761
+ exists = agreement_guid is not None and item_guid is not None
762
+
763
+ if directive == "display":
764
+
765
+ return None
766
+ elif directive == "validate":
767
+ if valid:
768
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
769
+ else:
770
+ msg = f"Validation failed for object_action `{command}`\n"
771
+ return valid
772
+
773
+ elif directive == "process":
774
+
775
+ try:
776
+ if object_action == "Detach":
777
+ if not exists:
778
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
779
+ f"object_action\n")
780
+ logger.error(msg)
781
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
782
+ return out
783
+ elif not valid:
784
+ return None
785
+ else:
786
+ print(Markdown(
787
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
788
+ body = set_delete_request_body(object_type, attributes)
789
+
790
+ egeria_client.detach_agreement_item(agreement_guid, item_guid, body)
791
+
792
+ logger.success(f"===> Detached agreement item `{item}` from agreement `{agreement}`\n")
793
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
794
+
795
+ return (out)
796
+
797
+ elif object_action == "Link":
798
+ if valid is False and exists:
799
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
800
+ f"`Link` to `Detach` in processed output\n")
801
+ logger.error(msg)
802
+
803
+ elif valid is False:
804
+ msg = f"==>{object_type} Link with Agreement `{agreement}` and item `{item}` is not valid and can't be created"
805
+ logger.error(msg)
806
+ return
807
+
808
+ else:
809
+ body = set_rel_request_body(object_type, attributes)
810
+ item_props = {
811
+ "class": "AgreementItemProperties",
812
+ "agreementItemId": attributes.get("Agreement Item Id", {}).get("value", None),
813
+ "agreementItemTypeName": attributes.get("Agreement Item Type", {}).get("value", None),
814
+ "agreementStart": attributes.get("Agreement Start", {}).get("value", None),
815
+ "agreementEnd": attributes.get("Agreement End", {}).get("value", None),
816
+ "restrictions": attributes.get("Restrictions", {}).get("value", None),
817
+ "obligations": attributes.get("Obligations", {}).get("value", None),
818
+ "entitlements": attributes.get("Entitlements", {}).get("value", None),
819
+ "usageMeasurements": attributes.get("Usage Measurements", {}).get("value", None),
820
+ "effectiveFrom": attributes.get("Effective From", {}).get("value", None),
821
+ "effectiveTo": attributes.get("Effective To", {}).get("value", None)
822
+
823
+ }
824
+ body['properties'] = item_props
825
+ egeria_client.link_agreement_item(agreement_guid,
826
+ item_guid, body)
827
+ msg = f"==>Linked {object_type} `{agreement} to item {item}\n"
828
+ logger.success(msg)
829
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
830
+ return out
831
+
832
+
833
+ except Exception as e:
834
+ logger.error(f"Error performing {command}: {e}")
835
+ return None
836
+ else:
837
+ return None
838
+
839
+
840
+ def process_add_to_collection_command(egeria_client: EgeriaTech, txt: str,
841
+ directive: str = "display") -> Optional[str]:
842
+ """
843
+ Processes a link or unlink command to add or remove a member to/from a collection..
844
+
845
+ :param txt: A string representing the input cell to be processed for
846
+ extracting blueprint-related attributes.
847
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
848
+ :return: A string summarizing the outcome of the processing.
849
+ """
850
+ command, object_type, object_action = extract_command_plus(txt)
851
+ print(Markdown(f"# {command}\n"))
852
+
853
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
854
+
855
+ print(Markdown(parsed_output['display']))
856
+
857
+ logger.debug(json.dumps(parsed_output, indent=4))
858
+
859
+ attributes = parsed_output['attributes']
860
+ element_guid = attributes.get('Element Id', {}).get('guid', None)
861
+ collection_guid = attributes.get('Collection Id', {}).get('guid', None)
862
+ membership_rationale = attributes.get('Membership Rationale', {}).get('value', None)
863
+ expression = attributes.get('Expression', {}).get('value', None)
864
+ confidence = attributes.get('Confidence', {}).get('value', None)
865
+ membership_status = attributes.get('Membership Status', {}).get('value', None)
866
+ user_defined_status = attributes.get('User Defined Status', {}).get('value', None)
867
+ steward = attributes.get('Steward', {}).get('guid', None)
868
+ steward_type_name = attributes.get('Steward Type Name', {}).get('value', None)
869
+ steward_property_name = attributes.get('Steward Property Name', {}).get('value', None)
870
+ source = attributes.get('Source', {}).get('value', None)
871
+ notes = attributes.get('Notes', {}).get('value', None)
872
+ glossary_term = attributes.get('Glossary Term', {}).get('value', None)
873
+ journal_entry = attributes.get('Journal Entry', {}).get('value', None)
874
+
875
+ valid = parsed_output['valid']
876
+ # exists = agreement_guid is not None and item_guid is not None
877
+ exists = collection_guid is not None and element_guid is not None
878
+
879
+ if directive == "display":
880
+
881
+ return None
882
+ elif directive == "validate":
883
+ if valid:
884
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
885
+ else:
886
+ msg = f"Validation failed for object_action `{command}`\n"
887
+ return valid
888
+
889
+ elif directive == "process":
890
+ prop_body = {
891
+ "class": "CollectionMembershipProperties",
892
+ "membershipRationale": membership_rationale,
893
+ "expression": expression,
894
+ "membershipStatus": membership_status,
895
+ "userDefinedStatus": user_defined_status,
896
+ "confidence": confidence,
897
+ "steward": steward,
898
+ "stewardTypeName": steward_type_name,
899
+ "stewardPropertyName": steward_property_name,
900
+ "source": source,
901
+ "notes": notes,
902
+ }
903
+ label = "Add Member"
904
+ try:
905
+ if object_action in ["Detach", "Unlink", "Remove"]:
906
+ if not exists:
907
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
908
+ f"object_action\n")
909
+ logger.error(msg)
910
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
911
+ return out
912
+ elif not valid:
913
+ return None
914
+ else:
915
+ print(Markdown(
916
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
917
+ body = set_delete_request_body(object_type, attributes)
918
+
919
+ egeria_client.remove_from_collection(collection_guid, element_guid, body)
920
+
921
+ logger.success(f"===> Detached element `{element_guid}` from collection `{collection_guid}`\n")
922
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
923
+
924
+ return (out)
925
+
926
+ elif object_action in ["Link", "Add", "Attach"]:
927
+ if valid is False and exists:
928
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
929
+ f"`Link` to `Detach` in processed output\n")
930
+ logger.error(msg)
931
+ if valid is False and exists:
932
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
933
+ f"`Link` to `Detach` in processed output\n")
934
+ logger.error(msg)
935
+
936
+ elif valid is False:
937
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
938
+ logger.error(msg)
939
+ return
940
+
941
+ else:
942
+ body = set_rel_request_body(object_type, attributes)
943
+
944
+ body['properties'] = prop_body
945
+ body = body_slimmer(body)
946
+ egeria_client.add_to_collection(collection_guid,
947
+ element_guid, body)
948
+ msg = f"==>Linked `{element_guid}` to collection `{collection_guid}` \n"
949
+ logger.success(msg)
950
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
951
+ return out
952
+
953
+
954
+ except Exception as e:
955
+ logger.error(f"Error performing {command}: {e}")
956
+ return None
957
+ else:
958
+ return None
959
+
960
+
961
+ def process_product_dependency_command(egeria_client: EgeriaTech, txt: str,
962
+ directive: str = "display") -> Optional[str]:
963
+ """
964
+ Processes a link or unlink command to associate or break up a dependency between digital products..
965
+
966
+ :param txt: A string representing the input cell to be processed for
967
+ extracting blueprint-related attributes.
968
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
969
+ :return: A string summarizing the outcome of the processing.
970
+ """
971
+ command, object_type, object_action = extract_command_plus(txt)
972
+ print(Markdown(f"# {command}\n"))
973
+
974
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
975
+
976
+ print(Markdown(parsed_output['display']))
977
+
978
+ logger.debug(json.dumps(parsed_output, indent=4))
979
+
980
+ attributes = parsed_output['attributes']
981
+ digital_product1_guid = attributes.get('Digital Product 1', None)
982
+ digital_product2_guid = attributes.get('Digital Product 2', None)
983
+ label = attributes.get('Label', {}).get('value', None)
984
+ description = attributes.get('Description', {}).get('value', None)
985
+ effective_from = attributes.get('Effective From', {}).get('value', None)
986
+ effective_to = attributes.get('Effective To', {}).get('value', None)
987
+
988
+ valid = parsed_output['valid']
989
+ exists = digital_product1_guid is not None and digital_product2_guid is not None
990
+
991
+ if directive == "display":
992
+
993
+ return None
994
+ elif directive == "validate":
995
+ if valid:
996
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
997
+ else:
998
+ msg = f"Validation failed for object_action `{command}`\n"
999
+ return valid
1000
+
1001
+ elif directive == "process":
1002
+ prop_body = {
1003
+ "class": "DigitalProductDependencyProperties",
1004
+ "label": label,
1005
+ "description": description,
1006
+ "effectiveFrom": effective_from,
1007
+ "effectiveTo": effective_to
1008
+ }
1009
+
1010
+ try:
1011
+ if object_action == "Detach":
1012
+ if not exists:
1013
+ msg = (f" Link `{label}` does not exist! Updating result document with Link "
1014
+ f"object_action\n")
1015
+ logger.error(msg)
1016
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1017
+ return out
1018
+ elif not valid:
1019
+ return None
1020
+ else:
1021
+ print(Markdown(
1022
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
1023
+ body = set_delete_request_body(object_type, attributes)
1024
+
1025
+ egeria_client.detach_digital_product_dependency(digital_product1_guid, digital_product2_guid, body)
1026
+
1027
+ logger.success(
1028
+ f"===> Detached dependency between products `{digital_product1_guid}` and `{digital_product2_guid}`\n")
1029
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
1030
+
1031
+ return (out)
1032
+
1033
+ elif object_action == "Link":
1034
+ if valid is False and exists:
1035
+ msg = (f"--> Link called `{label}` already exists and result document updated changing "
1036
+ f"`Link` to `Detach` in processed output\n")
1037
+ logger.error(msg)
1038
+
1039
+ elif valid is False:
1040
+ msg = f"==>{object_type} Link with label `{label}` is not valid and can't be created"
1041
+ logger.error(msg)
1042
+ return
1043
+
1044
+ else:
1045
+ body = set_rel_request_body(object_type, attributes)
1046
+
1047
+ body['properties'] = prop_body
1048
+ egeria_client.link_digital_product_dependency(digital_product1_guid,
1049
+ digital_product2_guid, body)
1050
+ msg = f"==>Linked dependency from digital product `{digital_product1_guid}` to product `{digital_product2_guid}` \n"
1051
+ logger.success(msg)
1052
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1053
+ return out
1054
+
1055
+
1056
+ except Exception as e:
1057
+ logger.error(f"Error performing {command}: {e}")
1058
+ return None
1059
+ else:
1060
+ return None
1061
+
1062
+
1063
+ def process_attach_collection_command(egeria_client: EgeriaTech, txt: str,
1064
+ directive: str = "display") -> Optional[str]:
1065
+ """
1066
+ Processes a link or unlink command to attach a collection to a resources.
1067
+
1068
+ :param txt: A string representing the input cell to be processed for
1069
+ extracting blueprint-related attributes.
1070
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1071
+ :return: A string summarizing the outcome of the processing.
1072
+ """
1073
+ command, object_type, object_action = extract_command_plus(txt)
1074
+ print(Markdown(f"# {command}\n"))
1075
+
1076
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
1077
+
1078
+ print(Markdown(parsed_output['display']))
1079
+
1080
+ logger.debug(json.dumps(parsed_output, indent=4))
1081
+
1082
+ attributes = parsed_output['attributes']
1083
+ collection_guid = attributes.get('Collection Id', {}).get('guid', None)
1084
+ resource_guid = attributes.get('Resource Id', {}).get('guid', None)
1085
+ resource_use = attributes.get('Resource Use', {}).get('value', None)
1086
+ resource_description = attributes.get('Resource Description', {}).get('value', None)
1087
+ resource_properties = attributes.get('Resource Properties', {}).get('value', None)
1088
+ effective_from = attributes.get('Effective From', {}).get('value', None)
1089
+ effective_to = attributes.get('Effective To', {}).get('value', None)
1090
+
1091
+ valid = parsed_output['valid']
1092
+ exists = collection_guid is not None and resource_guid is not None
1093
+
1094
+ if directive == "display":
1095
+
1096
+ return None
1097
+ elif directive == "validate":
1098
+ if valid:
1099
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
1100
+ else:
1101
+ msg = f"Validation failed for object_action `{command}`\n"
1102
+ return valid
1103
+
1104
+ elif directive == "process":
1105
+ prop_body = {
1106
+ "class": "ResourceListProperties",
1107
+ "resourceUse": resource_use,
1108
+ "resourceDescription": resource_description,
1109
+ "resourceProperties": resource_properties,
1110
+ "effectiveFrom": effective_from,
1111
+ "effectiveTo": effective_to
1112
+ }
1113
+
1114
+ try:
1115
+ if object_action == "Detach":
1116
+ if not exists:
1117
+ msg = (f" Link `Attach Resource to Collection` does not exist! Updating result document with Link "
1118
+ f"object_action\n")
1119
+ logger.error(msg)
1120
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1121
+ return out
1122
+ elif not valid:
1123
+ return None
1124
+ else:
1125
+ print(Markdown(
1126
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
1127
+ body = set_delete_request_body(object_type, attributes)
1128
+
1129
+ egeria_client.detach_collection(resource_guid, collection_guid, body)
1130
+
1131
+ logger.success(
1132
+ f"===> Detached linkage between resource `{resource_guid}` and collection`{collection_guid}`\n")
1133
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
1134
+
1135
+ return (out)
1136
+
1137
+ elif object_action == "Link":
1138
+ if valid is False and exists:
1139
+ msg = (
1140
+ f"--> Link called `Attach Resource to Collection` already exists and result document updated changing "
1141
+ f"`Link` to `Detach` in processed output\n")
1142
+ logger.error(msg)
1143
+
1144
+ elif valid is False:
1145
+ msg = f"==>{object_type} Link with label `Attach Resource to Collection` is not valid and can't be created"
1146
+ logger.error(msg)
1147
+ return
1148
+
1149
+ else:
1150
+ body = set_rel_request_body(object_type, attributes)
1151
+
1152
+ body['properties'] = prop_body
1153
+ egeria_client.attach_collection(resource_guid,
1154
+ collection_guid, body)
1155
+ msg = f"==>Attached collection `{collection_guid}` to resource `{resource_guid}` \n"
1156
+ logger.success(msg)
1157
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1158
+ return out
1159
+
1160
+
1161
+ except Exception as e:
1162
+ logger.error(f"Error performing {command}: {e}")
1163
+ return None
1164
+ else:
1165
+ return None
1166
+
1167
+
1168
+ def process_attach_subscriber_command(egeria_client: EgeriaTech, txt: str,
1169
+ directive: str = "display") -> Optional[str]:
1170
+ """
1171
+ Processes a link or unlink command to attach a subscriber to a subscription.
1172
+
1173
+ :param txt: A string representing the input cell to be processed for
1174
+ extracting blueprint-related attributes.
1175
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1176
+ :return: A string summarizing the outcome of the processing.
1177
+ """
1178
+ command, object_type, object_action = extract_command_plus(txt)
1179
+ print(Markdown(f"# {command}\n"))
1180
+
1181
+ parsed_output = parse_view_command(egeria_client, object_type, object_action, txt, directive)
1182
+ if parsed_output is None:
1183
+ logger.error(f"Input error in command `{txt}`")
1184
+ return None
1185
+
1186
+ print(Markdown(parsed_output['display']))
1187
+
1188
+ logger.debug(json.dumps(parsed_output, indent=4))
1189
+
1190
+ attributes = parsed_output['attributes']
1191
+ subscriber_guid = attributes.get('Subscriber Id', {}).get('guid', None)
1192
+ subscription_guid = attributes.get('Subscription', {}).get('guid', None)
1193
+
1194
+ valid = parsed_output['valid']
1195
+ exists = subscriber_guid is not None and subscription_guid is not None
1196
+ if directive == "display":
1197
+
1198
+ return None
1199
+ elif directive == "validate":
1200
+ if valid:
1201
+ print(Markdown(f"==> Validation of {command} completed successfully!\n"))
1202
+ else:
1203
+ msg = f"Validation failed for object_action `{command}`\n"
1204
+ return valid
1205
+
1206
+ elif directive == "process":
1207
+ prop_body = {
1208
+ "class": "DigitalSubscriberProperties",
1209
+ "subscriberId": attributes.get('Subscriber Id', {}).get('value', None),
1210
+ "effectiveFrom": attributes.get('Effective From', {}).get('value', None),
1211
+ "effectiveTo": attributes.get('Effective To', {}).get('value', None),
1212
+ }
1213
+
1214
+ try:
1215
+ if object_action == "Detach":
1216
+ if not exists:
1217
+ msg = (
1218
+ f" Link `Attach Subscriber to Subscription` does not exist! Updating result document with Link "
1219
+ f"object_action\n")
1220
+ logger.error(msg)
1221
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1222
+ return out
1223
+ elif not valid:
1224
+ return None
1225
+ else:
1226
+ print(Markdown(
1227
+ f"==> Validation of {command} completed successfully! Proceeding to apply the changes.\n"))
1228
+ body = set_delete_request_body(object_type, attributes)
1229
+
1230
+ egeria_client.detach_subscriber(subscriber_guid, subscription_guid, body)
1231
+
1232
+ logger.success(
1233
+ f"===> Detached linkage between subscriber `{subscriber_guid}` and subscription`{subscription_guid}`\n")
1234
+ out = parsed_output['display'].replace('Unlink', 'Link', 1)
1235
+
1236
+ return (out)
1237
+
1238
+ elif object_action == "Link":
1239
+ if valid is False and exists:
1240
+ msg = (
1241
+ f"--> Link called `Attach Subscriber to Subscription` already exists and result document updated changing "
1242
+ f"`Link` to `Detach` in processed output\n")
1243
+ logger.error(msg)
1244
+
1245
+ elif valid is False:
1246
+ msg = f"==>{object_type} Subscription link `{subscriber_guid}` is not valid and can't be created"
1247
+ logger.error(msg)
1248
+ return
1249
+
1250
+ else:
1251
+ body = set_rel_request_body(object_type, attributes)
1252
+
1253
+ body['properties'] = prop_body
1254
+ egeria_client.link_subscriber(subscriber_guid,
1255
+ subscription_guid, body)
1256
+ msg = f"==>Attached subscriber `{subscriber_guid}` to subscription `{subscriber_guid}` \n"
1257
+ logger.success(msg)
1258
+ out = parsed_output['display'].replace('Link', 'Detach', 1)
1259
+ return out
1260
+
1261
+
1262
+ except Exception as e:
1263
+ logger.error(f"Error performing {command}: {e}")
1264
+ return None
1265
+ else:
1266
+ return None