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,3231 @@
1
+ """
2
+ SPDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ This module contains an initial version of the glossary_manager module.
6
+
7
+ """
8
+
9
+ import asyncio
10
+ import csv
11
+ import os
12
+ from typing import List, Annotated, Literal, Optional
13
+
14
+ from loguru import logger
15
+ from pydantic import Field
16
+
17
+ from pyegeria.core._exceptions import PyegeriaInvalidParameterException
18
+ from pyegeria.core._globals import NO_GUID_RETURNED
19
+ from pyegeria.core._validators import validate_guid
20
+ from pyegeria.omvs.collection_manager import CollectionManager
21
+ from pyegeria.core.config import settings as app_settings
22
+ from pyegeria.models import (NewElementRequestBody, DeleteElementRequestBody, DeleteRelationshipRequestBody,
23
+ ReferenceableProperties, UpdateElementRequestBody, TemplateRequestBody,
24
+ NewRelationshipRequestBody, UpdateRelationshipRequestBody, NewClassificationRequestBody,
25
+ FilterRequestBody, GetRequestBody, SearchStringRequestBody,
26
+ DeleteClassificationRequestBody)
27
+ from pyegeria.view.output_formatter import (generate_output,
28
+ _extract_referenceable_properties, populate_common_columns,
29
+ overlay_additional_values, resolve_output_formats)
30
+ from pyegeria.core.utils import body_slimmer, dynamic_catch
31
+
32
+ EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
33
+
34
+
35
+
36
+ class GlossaryProperties(ReferenceableProperties):
37
+ class_: Annotated[Literal["GlossaryProperties"], Field(alias="class")]
38
+ language: str = "English"
39
+ usage: str = None
40
+
41
+
42
+ class GlossaryTermProperties(ReferenceableProperties):
43
+ class_: Annotated[Literal["GlossaryTermProperties"], Field(alias="class")]
44
+ summary: str = None
45
+ description: str = None
46
+ abbreviation: str = None
47
+ examples: str = None
48
+ usage: str = None
49
+ user_defined_status: str = None
50
+ publishVersionIdentifier: str = None
51
+
52
+
53
+ class GlossaryManager(CollectionManager):
54
+ """
55
+ Client for the Glossary Manager View Service.
56
+
57
+ The Glossary Manager View Service provides methods to create and manage glossaries,
58
+ terms, and categories.
59
+
60
+ Attributes
61
+ ----------
62
+ view_server : str
63
+ The name of the View Server to connect to.
64
+ platform_url : str
65
+ URL of the server platform to connect to.
66
+ user_id : str
67
+ The identity of the user calling the method.
68
+ user_pwd : str
69
+ The password associated with the user_id. Defaults to None.
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ view_server: str,
75
+ platform_url: str,
76
+ user_id: str,
77
+ user_pwd: Optional[str] = None,
78
+ token: Optional[str] = None,
79
+ ):
80
+ self.view_server = view_server
81
+ self.platform_url = platform_url
82
+ self.user_id = user_id
83
+ self.user_pwd = user_pwd
84
+ self.url_marker = "glossary-manager"
85
+
86
+
87
+ CollectionManager.__init__(self, view_server, platform_url, user_id, user_pwd, token)
88
+ # result = self.get_platform_origin()
89
+ # logger.info(f"GlossaryManager initialized, platform origin is: {result}")
90
+ self.glossary_command_root = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager"
91
+ #
92
+ # Get Valid Values for Enumerations
93
+ #
94
+
95
+ def __validate_term_status__(self, status: str) -> bool:
96
+ """Return True if the status is a legal glossary term status"""
97
+ recognized_term_status = self.get_glossary_term_statuses()
98
+ return status in recognized_term_status
99
+
100
+ #
101
+ # Glossaries
102
+ #
103
+
104
+
105
+
106
+ @dynamic_catch
107
+ async def _async_create_glossary(self, display_name: str, description: Optional[str] = None, language: str = "English", usage: Optional[str] = None,
108
+ category: Optional[str] = None, body: Optional[dict | NewElementRequestBody] = None) -> str:
109
+ """Create a new glossary. Async version.
110
+
111
+ Parameters
112
+ ----------
113
+ display_name : str
114
+ The name of the glossary.
115
+ description : str, optional
116
+ The description of the glossary.
117
+ language : str, optional
118
+ The language of the glossary (default is "English").
119
+ usage : str, optional
120
+ The usage information for the glossary.
121
+ category : str, optional
122
+ The category for the glossary.
123
+ body : dict | NewElementRequestBody, optional
124
+ If provided, the request body for creating the glossary.
125
+
126
+ Returns
127
+ -------
128
+ str
129
+ The GUID of the newly created glossary.
130
+
131
+ Raises
132
+ ------
133
+ PyegeriaException
134
+ If there are issues in communications, message format, or Egeria errors.
135
+ """
136
+ if body is None:
137
+ qualified_name = self.__create_qualified_name__("Glossary", display_name, EGERIA_LOCAL_QUALIFIER)
138
+ body = {
139
+ "class": "NewElementRequestBody",
140
+ "is_own_anchor": True,
141
+ "properties": {
142
+ "class": "GlossaryProperties",
143
+ "displayName": display_name,
144
+ "qualifiedName": qualified_name,
145
+ "description": description,
146
+ "language": language,
147
+ "usage": usage,
148
+ "category": category
149
+ },
150
+ }
151
+ response = await self._async_create_collection(body=body)
152
+ return response
153
+
154
+ def create_glossary(self, display_name: str, description: Optional[str] = None, language: str = "English",
155
+ usage: Optional[str] = None,
156
+ category: Optional[str] = None, body: Optional[dict | NewElementRequestBody] = None) -> str:
157
+ """Create a new glossary.
158
+
159
+ Parameters
160
+ ----------
161
+ display_name : str
162
+ The name of the glossary.
163
+ description : str, optional
164
+ The description of the glossary.
165
+ language : str, optional
166
+ The language of the glossary (default is "English").
167
+ usage : str, optional
168
+ The usage information for the glossary.
169
+ category : str, optional
170
+ The category for the glossary.
171
+ body : dict | NewElementRequestBody, optional
172
+ If provided, the request body for creating the glossary.
173
+
174
+ Returns
175
+ -------
176
+ str
177
+ The GUID of the newly created glossary.
178
+
179
+ Raises
180
+ ------
181
+ PyegeriaException
182
+ If there are issues in communications, message format, or Egeria errors.
183
+ """
184
+ loop = asyncio.get_event_loop()
185
+ response = loop.run_until_complete(
186
+ self._async_create_glossary(display_name, description, language, usage, category, body)
187
+ )
188
+ return response
189
+
190
+ async def _async_delete_glossary(self, glossary_guid: str, body: Optional[dict | DeleteElementRequestBody] = None,
191
+ cascade: bool = False) -> None:
192
+ """Delete glossary. Async version.
193
+
194
+ Parameters
195
+ ----------
196
+ glossary_guid: str
197
+ The ID of the glossary to delete.
198
+ cascade: bool, optional, default = False
199
+ If true, then delete all terms and categories in the glossary as well.
200
+
201
+ Returns
202
+ -------
203
+ None
204
+
205
+ """
206
+
207
+ await self._async_delete_collection(glossary_guid, body, cascade)
208
+
209
+ logger.info(f"Deleted glossary {glossary_guid} with cascade {cascade}")
210
+
211
+ def delete_glossary(self, glossary_guid: str, body: Optional[dict | DeleteElementRequestBody] = None, cascade: bool = False) -> None:
212
+ """Delete a new glossary.
213
+
214
+ Parameters
215
+ ----------
216
+ glossary_guid: str
217
+ The ID of the glossary to delete.
218
+ cascade: bool, optional, default = False
219
+ If true, then delete all terms and categories in the glossary as well.
220
+
221
+
222
+ Returns
223
+ -------
224
+ None
225
+
226
+ """
227
+ loop = asyncio.get_event_loop()
228
+ loop.run_until_complete(self._async_delete_glossary(glossary_guid, body, cascade))
229
+
230
+ async def _async_update_glossary(
231
+ self,
232
+ glossary_guid: str,
233
+ body: dict | UpdateElementRequestBody,
234
+ merge_update: bool = True,
235
+ ) -> None:
236
+ """Update Glossary.
237
+
238
+ Async version.
239
+
240
+ Parameters
241
+ ----------
242
+ glossary_guid: str
243
+ The ID of the glossary to update.
244
+ body: dict
245
+ A dict containing the properties to update.
246
+
247
+ Returns
248
+ -------
249
+ None
250
+
251
+ Notes
252
+ -----
253
+
254
+ Sample body:
255
+
256
+ """
257
+
258
+
259
+
260
+ await self._async_update_collection(glossary_guid, body)
261
+ logger.info(f"Updated glossary {glossary_guid}")
262
+
263
+ def update_glossary(
264
+ self,
265
+ glossary_guid: str,
266
+ body: dict | UpdateElementRequestBody,
267
+ merge_update: bool = True,
268
+ ) -> None:
269
+ """Update Glossary.
270
+
271
+ Parameters
272
+ ----------
273
+ glossary_guid: str
274
+ The ID of the glossary to update.
275
+ body: dict
276
+ A dict containing the properties to update.
277
+ is_merge_update: bool, optional, default = True
278
+ If true, then only those properties specified in the body will be updated. If false, then all the
279
+ properties of the glossary will be replaced with those of the body.
280
+
281
+
282
+ Returns
283
+ -------
284
+ None
285
+
286
+ Notes
287
+ -----
288
+
289
+ Sample body:
290
+
291
+
292
+ """
293
+ loop = asyncio.get_event_loop()
294
+ loop.run_until_complete(
295
+ self._async_update_glossary(
296
+ glossary_guid,
297
+ body, merge_update
298
+ )
299
+ )
300
+
301
+ #
302
+ # add glossary classifications? is-canonical, is editing, is staging, is taxonomy?
303
+ # Not all show up in UML
304
+
305
+
306
+
307
+ #
308
+ # Terms
309
+ #
310
+ async def _async_create_glossary_term(
311
+ self, body: dict | NewElementRequestBody
312
+ ) -> str:
313
+ """Create a term for a glossary. Async version.
314
+
315
+ Parameters
316
+ ----------
317
+ body : dict | NewElementRequestBody
318
+ The request body for creating the glossary term.
319
+
320
+ Returns
321
+ -------
322
+ str
323
+ The unique GUID for the created term.
324
+
325
+ Raises
326
+ ------
327
+ PyegeriaException
328
+ If there are issues in communications, message format, or Egeria errors.
329
+ """
330
+
331
+ url = (
332
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms"
333
+ )
334
+ return await self._async_create_element_body_request(url, "GlossaryTermProperties", body)
335
+
336
+ def create_glossary_term(self, body: dict | NewElementRequestBody) -> str:
337
+ """Create a term for a glossary.
338
+
339
+ Parameters
340
+ ----------
341
+ body : dict | NewElementRequestBody
342
+ The request body for creating the glossary term.
343
+
344
+ Returns
345
+ -------
346
+ str
347
+ The unique GUID for the created term.
348
+
349
+ Raises
350
+ ------
351
+ PyegeriaException
352
+ If there are issues in communications, message format, or Egeria errors.
353
+ """
354
+ loop = asyncio.get_event_loop()
355
+ response = loop.run_until_complete(
356
+ self._async_create_glossary_term(body)
357
+ )
358
+
359
+ return response
360
+
361
+ def load_terms_from_csv_file(
362
+ self,
363
+ glossary_name: str,
364
+ filename: str,
365
+ file_path: str = os.environ.get("EGERIA_GLOSSARY_PATH", None),
366
+ upsert: bool = True,
367
+ verbose: bool = True,
368
+ ) -> List[dict] | None:
369
+ """This method loads glossary terms into the specified glossary from the indicated file.
370
+
371
+ Parameters
372
+ ----------
373
+ glossary_name : str
374
+ Name of the glossary to import terms into.
375
+ file_path: str, default is EGERIA_GLOSSARY_PATH if specified or None
376
+ If EGERIA_GLOSSARY_PATH environment variable is set, then it will be used in forming the
377
+ prepended to the filename parameter to form the full path to the file.
378
+ filename: str
379
+ Path to the file to import terms from. File is assumed to be in CSV format. The path
380
+ is relative to where the python method is being called from.
381
+ upsert: bool, default = True
382
+ If true, terms from the file are inserted into the glossary if no qualified name is specified;
383
+ if a qualified name is specified in the file, then the file values for this term will over-ride the
384
+ values in the glossary. If false, the row in the file will be appended to the glossary, possibly
385
+ resulting in duplicate term names - which is legal (since the qualified names will be unique).
386
+
387
+ verbose: bool, default = True
388
+ If true, a JSON structure will be returned indicating the import status of each row.
389
+
390
+
391
+ Returns
392
+ -------
393
+ [dict]:
394
+ If verbose is True, import status for each row
395
+ None:
396
+ If verbose is False
397
+
398
+ Raises
399
+ ------
400
+ PyegeriaInvalidParameterException
401
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
402
+ PyegeriaAPIException
403
+ Raised by the server when an issue arises in processing a valid request.
404
+ NotAuthorizedException
405
+ The principle specified by the user_id does not have authorization for the requested action.
406
+ Notes
407
+ -----
408
+ Keep in mind that the file path is relative to where the python method is being called from -
409
+ not relative to the Egeria platform.
410
+
411
+ """
412
+
413
+ # Check that glossary exists and get guid
414
+ glossaries = self.get_glossaries_by_name(glossary_name)
415
+ if type(glossaries) is not list:
416
+ return "Unknown glossary"
417
+ if len(glossaries) > 1:
418
+ glossary_error = (
419
+ "Multiple glossaries found - please use a qualified name from below\n"
420
+ )
421
+ for g in glossaries:
422
+ glossary_error += (
423
+ f"Display Name: {g['glossaryProperties']['displayName']}\tQualified Name:"
424
+ f" {g['glossaryProperties']['qualifiedName']}\n"
425
+ )
426
+ raise Exception(glossary_error)
427
+ sys.exit(1)
428
+
429
+ # Now we know we have a single glossary so we can get the guid
430
+ glossary_guid = glossaries[0]["elementHeader"]["guid"]
431
+
432
+ term_properties = {
433
+ "Term Name",
434
+ "Qualified Name",
435
+ "Abbreviation",
436
+ "Summary",
437
+ "Description",
438
+ "Examples",
439
+ "Usage",
440
+ "Version Identifier",
441
+ "Status",
442
+ }
443
+
444
+ if file_path:
445
+ full_file_path = os.path.join(file_path, filename)
446
+ else:
447
+ full_file_path = filename
448
+
449
+ if not os.path.isfile(full_file_path):
450
+ raise FileNotFoundError(
451
+ f"Did not find file with path {file_path} and name {filename}"
452
+ )
453
+ # process file
454
+ with open(full_file_path, mode="r") as file:
455
+ # Create a CSV reader object
456
+ csv_reader = csv.DictReader(file)
457
+ headers = csv_reader.fieldnames
458
+ term_info = []
459
+ # check that the column headers are known
460
+ if all(header in term_properties for header in headers) is False:
461
+ raise PyegeriaInvalidParameterException(
462
+ None,
463
+ context={"caller_method": "load_terms_from_csv"},
464
+ additional_info={"reason": "Invalid headers in CSV File"},
465
+ )
466
+
467
+ # process each row and validate values
468
+ for row in csv_reader:
469
+ # Parse the file. When the value '---' is encountered, make the value None.git+https:
470
+ term_name = row.get("Term Name", " ")
471
+ if len(term_name) < 2:
472
+ term_info.append(
473
+ {
474
+ "term_name": "---",
475
+ "qualified_name": "---",
476
+ "term_guid": "---",
477
+ "error": "missing or invalid term names - skipping",
478
+ }
479
+ )
480
+ continue
481
+ qualified_name = row.get("Qualified Name", None)
482
+ abbrev_in = row.get("Abbreviation", None)
483
+ abbrev = None if abbrev_in == "---" else abbrev_in
484
+
485
+ summary_in = row.get("Summary", None)
486
+ summary = None if summary_in == "---" else summary_in
487
+
488
+ description_in = row.get("Description", None)
489
+ description = None if description_in == "---" else description_in
490
+
491
+ examples_in = row.get("Examples", None)
492
+ examples = None if examples_in == "---" else examples_in
493
+
494
+ usage_in = row.get("Usage", None)
495
+ usage = None if usage_in == "---" else usage_in
496
+
497
+ version = row.get("Version Identifier", "1.0")
498
+ status = row.get("Status", "DRAFT").upper()
499
+ if self.__validate_term_status__(status) is False:
500
+ term_info.append(
501
+ {
502
+ "term_name": "---",
503
+ "qualified_name": "---",
504
+ "term_guid": "---",
505
+ "error": "invalid term status",
506
+ }
507
+ )
508
+ continue
509
+
510
+ if upsert:
511
+ # If upsert is set we need to see if it can be done (there must be a valid qualified name) and then
512
+ # do the update for the row - if there is no qualified name we will treat the row as an insert.
513
+ if qualified_name:
514
+ term_stuff = self.get_terms_by_name(
515
+ qualified_name, glossary_guid
516
+ )
517
+ if type(term_stuff) is str:
518
+ # An existing term was not found with that qualified name
519
+ term_info.append(
520
+ {
521
+ "term_name": term_name,
522
+ "qualified_name": qualified_name,
523
+ "error": "Matching term not found - skipping",
524
+ }
525
+ )
526
+ continue
527
+ elif len(term_stuff) > 1:
528
+ term_info.append(
529
+ {
530
+ "term_name": term_name,
531
+ "qualified_name": qualified_name,
532
+ "error": "Multiple matching terms - skipping",
533
+ }
534
+ )
535
+ continue
536
+ else:
537
+ # An existing term was found - so update it! Get the existing values and overlay
538
+ # values from file when present
539
+
540
+ body = {
541
+ "class": "ReferenceableRequestBody",
542
+ "elementProperties": {
543
+ "class": "GlossaryTermProperties",
544
+ "qualifiedName": qualified_name,
545
+ "displayName": term_name,
546
+ "summary": summary,
547
+ "description": description,
548
+ "abbreviation": abbrev,
549
+ "examples": examples,
550
+ "usage": usage,
551
+ "publishVersionIdentifier": version,
552
+ },
553
+ "updateDescription": "Update from file import via upsert",
554
+ }
555
+ term_guid = term_stuff[0]["elementHeader"]["guid"]
556
+ self.update_term(
557
+ term_guid, body_slimmer(body), is_merge_update=True
558
+ )
559
+ term_info.append(
560
+ {
561
+ "term_name": term_name,
562
+ "qualified_name": qualified_name,
563
+ "term_guid": term_guid,
564
+ "updated": "the term was updated",
565
+ }
566
+ )
567
+ continue
568
+
569
+ # Add the term
570
+ term_qualified_name = self.__create_qualified_name__("Term", term_name)
571
+
572
+ body = {
573
+ "class": "ReferenceableRequestBody",
574
+ "elementProperties": {
575
+ "class": "GlossaryTermProperties",
576
+ "qualifiedName": term_qualified_name,
577
+ "displayName": term_name,
578
+ "summary": summary,
579
+ "description": description,
580
+ "abbreviation": abbrev,
581
+ "examples": examples,
582
+ "usage": usage,
583
+ "publishVersionIdentifier": version,
584
+ },
585
+ "initialStatus": status,
586
+ }
587
+
588
+ # Add the term
589
+ term_guid = self.create_controlled_glossary_term(
590
+ glossary_guid, body_slimmer(body)
591
+ )
592
+ term_info.append(
593
+ {
594
+ "term_name": term_name,
595
+ "qualified_name": term_qualified_name,
596
+ "term_guid": term_guid,
597
+ }
598
+ )
599
+ if verbose:
600
+ return term_info
601
+ else:
602
+ return
603
+
604
+ async def _async_export_glossary_to_csv(
605
+ self,
606
+ glossary_guid: str,
607
+ target_file: str,
608
+ file_path: str = os.environ.get("EGERIA_GLOSSARY_PATH", None),
609
+ ) -> int:
610
+ """Export all the terms in a glossary to a CSV file. Async version
611
+
612
+ Parameters:
613
+ -----------
614
+ glossary_guid: str
615
+ Identity of the glossary to export.
616
+ target_file: str
617
+ Complete file name with path and extension to export to.
618
+ input_file: str, default is EGERIA_GLOSSARY_PATH if specified or None
619
+ If EGERIA_GLOSSARY_PATH environment variable is set, then it will be used in forming the
620
+ prepended to the filename parameter to form the full path to the file.
621
+
622
+ Returns:
623
+ int: Number of rows exported.
624
+ """
625
+
626
+ term_list = await self._async_get_terms_for_glossary(glossary_guid)
627
+
628
+ header = [
629
+ "Term Name",
630
+ "Qualified Name",
631
+ "Abbreviation",
632
+ "Summary",
633
+ "Description",
634
+ "Examples",
635
+ "Usage",
636
+ "Version Identifier",
637
+ "Status",
638
+ ]
639
+ if file_path:
640
+ full_file_path = os.path.join(file_path, target_file)
641
+ else:
642
+ full_file_path = target_file
643
+
644
+ with open(full_file_path, mode="w") as file:
645
+ csv_writer = csv.DictWriter(file, fieldnames=header)
646
+ csv_writer.writeheader()
647
+ count = 0
648
+ for term in term_list:
649
+ term_name = term["glossaryTermProperties"]["displayName"]
650
+ qualified_name = term["glossaryTermProperties"]["qualifiedName"]
651
+ abbrev = term["glossaryTermProperties"].get("abbreviation", "---")
652
+ summary = term["glossaryTermProperties"].get("summary", "---")
653
+ description = term["glossaryTermProperties"].get("description", "---")
654
+ examples = term["glossaryTermProperties"].get("examples", "---")
655
+ usage = term["glossaryTermProperties"].get("usage", "---")
656
+ version = term["glossaryTermProperties"].get(
657
+ "publishVersionIdentifier", "---"
658
+ )
659
+ status = term["elementHeader"]["status"]
660
+
661
+ csv_writer.writerow(
662
+ {
663
+ "Term Name": term_name,
664
+ "Qualified Name": qualified_name,
665
+ "Abbreviation": abbrev,
666
+ "Summary": summary,
667
+ "Description": description,
668
+ "Examples": examples,
669
+ "Usage": usage,
670
+ "Version Identifier": version,
671
+ "Status": status,
672
+ }
673
+ )
674
+
675
+ count += 1
676
+ return count
677
+
678
+ def export_glossary_to_csv(
679
+ self,
680
+ glossary_guid: str,
681
+ target_file: str,
682
+ file_path: str = os.environ.get("EGERIA_GLOSSARY_PATH", None),
683
+ ) -> int:
684
+ """Export all the terms in a glossary to a CSV file.
685
+
686
+ Parameters:
687
+ -----------
688
+ glossary_guid: str
689
+ Identity of the glossary to export.
690
+ target_file: str
691
+ Complete file name with path and extension to export to.
692
+ input_file: str, default is EGERIA_GLOSSARY_PATH if specified or None
693
+ If EGERIA_GLOSSARY_PATH environment variable is set, then it will be used in forming the
694
+ prepended to the filename parameter to form the full path to the file.
695
+
696
+ Returns:
697
+ int: Number of rows exported.
698
+ """
699
+
700
+ loop = asyncio.get_event_loop()
701
+ response = loop.run_until_complete(
702
+ self._async_export_glossary_to_csv(glossary_guid, target_file, file_path)
703
+ )
704
+
705
+ return response
706
+
707
+ async def _async_create_term_copy(
708
+ self,
709
+ glossary_guid: str,
710
+ glossary_term_guid: str,
711
+ new_display_name: str,
712
+ version_id: Optional[str] = None,
713
+ term_status: str = "PROPOSED",
714
+ body: Optional[dict | TemplateRequestBody] = None,
715
+ ) -> str:
716
+ """Create a new term from an existing term.
717
+
718
+ Async Version.
719
+
720
+ Parameters
721
+ ----------
722
+ glossary_guid : str
723
+ Unique identifier for the glossary category to retrieve terms from.
724
+ glossary_term_guid: str
725
+ Unique identifier for the source glossary term.
726
+ new_display_name: str
727
+ The display name of the new term.
728
+ version_id: str
729
+ The version identifier of the new term.
730
+ term_status: str, optional, default = "PROPOSED"
731
+ The status of the term
732
+
733
+
734
+ Returns
735
+ -------
736
+ str:
737
+ The unique guid for the created term.
738
+
739
+ Raises
740
+ ------
741
+ PyegeriaInvalidParameterException
742
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
743
+ PyegeriaAPIException
744
+ Raised by the server when an issue arises in processing a valid request.
745
+ NotAuthorizedException
746
+ The principle specified by the user_id does not have authorization for the requested action.
747
+ Notes
748
+ -----
749
+
750
+ """
751
+
752
+ if isinstance(body, TemplateRequestBody):
753
+ validated_body = body
754
+
755
+ elif isinstance(body, dict):
756
+ validated_body = self._template_request_adapter.validate_python(body)
757
+ else:
758
+ qualified_name = self.__create_qualified_name__("Term", new_display_name, EGERIA_LOCAL_QUALIFIER)
759
+ body = {
760
+ "class" : "TemplateRequestBody",
761
+ "templateGUID": glossary_term_guid,
762
+ "parentGuid": glossary_guid,
763
+ "parentAtEnd1": True,
764
+
765
+ "replacementProperties": {
766
+ "class": "GlossaryTermProperties",
767
+ "qualifiedName": qualified_name,
768
+ "displayName": new_display_name,
769
+ "status": term_status,
770
+ "versionIdentifier": version_id
771
+ },
772
+ }
773
+ validated_body = self._template_request_adapter.validate_python(body)
774
+ validated_body._templateGUID = glossary_term_guid
775
+ v_body = body_slimmer(validated_body.model_dump(exclude_none=True))
776
+ logger.info(v_body)
777
+
778
+ url = (
779
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
780
+ f"terms/from-template/{glossary_term_guid}"
781
+ )
782
+
783
+ resp = await self._async_make_request("POST", url, v_body)
784
+ guid = resp.json().get("guid", NO_GUID_RETURNED)
785
+ logger.info(f"Create Term from template with GUID: {guid}")
786
+ return guid
787
+
788
+ def create_term_copy(
789
+ self,
790
+ glossary_guid: str,
791
+ glossary_term_guid: str,
792
+ new_display_name: str,
793
+ version_id: Optional[str] = None,
794
+ term_status: str = "PROPOSED",
795
+ body: Optional[dict | TemplateRequestBody] = None,
796
+ ) -> str:
797
+ """Create a new term from an existing term.
798
+
799
+ Parameters
800
+ ----------
801
+ glossary_guid : str
802
+ Unique identifier for the glossary category to retrieve terms from.
803
+ glossary_term_guid: str
804
+ Unique identifier for the source glossary term.
805
+ new_display_name: str
806
+ The display name of the new term.
807
+ version_id: str
808
+ The version identifier of the new term.
809
+ term_status: str, optional, default = "PROPOSED"
810
+ The status of the term
811
+
812
+
813
+ Returns
814
+ -------
815
+ str:
816
+ The unique guid for the created term.
817
+
818
+ Raises
819
+ ------
820
+ PyegeriaInvalidParameterException
821
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
822
+ PyegeriaAPIException
823
+ Raised by the server when an issue arises in processing a valid request.
824
+ NotAuthorizedException
825
+ The principle specified by the user_id does not have authorization for the requested action.
826
+ Notes
827
+ -----
828
+
829
+ """
830
+ loop = asyncio.get_event_loop()
831
+ response = loop.run_until_complete(
832
+ self._async_create_term_copy(
833
+ glossary_guid,
834
+ glossary_term_guid,
835
+ new_display_name,
836
+ version_id,
837
+ term_status,
838
+ body,
839
+ )
840
+ )
841
+
842
+ return response
843
+
844
+ @dynamic_catch
845
+ async def _async_update_glossary_term(
846
+ self,
847
+ glossary_term_guid: str,
848
+ body: dict | UpdateElementRequestBody,
849
+ ) -> None:
850
+ """Update a term. Async version.
851
+
852
+ Parameters
853
+ ----------
854
+ glossary_term_guid: str
855
+ Unique identifier for the source glossary term.
856
+ body: dict
857
+ Body containing information about the data field to add
858
+
859
+
860
+ Returns
861
+ -------
862
+ None
863
+
864
+ Raises
865
+ ------
866
+ PyegeriaInvalidParameterException
867
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
868
+ PyegeriaAPIException
869
+ Raised by the server when an issue arises in processing a valid request.
870
+ NotAuthorizedException
871
+ The principle specified by the user_id does not have authorization for the requested action.
872
+ Notes
873
+ -----
874
+
875
+ """
876
+
877
+ validate_guid(glossary_term_guid)
878
+
879
+ url = (
880
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms/"
881
+ f"{glossary_term_guid}/"
882
+ f"update"
883
+ )
884
+ await self._async_update_element_body_request(url, ["GlossaryTermProperties"], body)
885
+ logger.info(f"Updated digital subscription {glossary_term_guid}")
886
+ @dynamic_catch
887
+ def update_glossary_term(
888
+ self,
889
+ glossary_term_guid: str,
890
+ body: dict | UpdateElementRequestBody,
891
+
892
+ ) -> None:
893
+ """Add the data field values classification to a glossary term
894
+
895
+ Async Version.
896
+
897
+ Parameters
898
+ ----------
899
+ glossary_term_guid: str
900
+ Unique identifier for the source glossary term.
901
+ body: dict
902
+ Body containing information about the data field to add
903
+ is_merge_update: bool, optional, default = True
904
+ Whether the data field values should be merged with existing definition or replace it.
905
+
906
+
907
+ Returns
908
+ -------
909
+ None
910
+
911
+ Raises
912
+ ------
913
+ PyegeriaInvalidParameterException
914
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
915
+ PyegeriaAPIException
916
+ Raised by the server when an issue arises in processing a valid request.
917
+ NotAuthorizedException
918
+ The principle specified by the user_id does not have authorization for the requested action.
919
+ Notes
920
+ -----
921
+ An example body is:
922
+
923
+ {
924
+ "class" : "ReferenceableRequestBody",
925
+ "elementProperties" :
926
+ {
927
+ "class" : "GlossaryTermProperties",
928
+ "description" : "This is the long description of the term. And this is some more text."
929
+ },
930
+ "updateDescription" : "Final updates based on in-house review comments."
931
+ }
932
+
933
+ """
934
+ loop = asyncio.get_event_loop()
935
+ loop.run_until_complete(
936
+ self._async_update_glossary_term(
937
+ glossary_term_guid,
938
+ body,
939
+ )
940
+ )
941
+
942
+ @dynamic_catch
943
+ async def _async_update_glossary_term_status(
944
+ self,
945
+ glossary_term_guid: str,
946
+ term_status: str = "DRAFT",
947
+ body: Optional[dict | UpdateElementRequestBody] = None,
948
+ ) -> None:
949
+ """Update the status of a term. Async version.
950
+
951
+ Parameters
952
+ ----------
953
+ glossary_term_guid: str
954
+ Unique identifier for the source glossary term.
955
+ term_status: str
956
+ new status of the term.
957
+ body: dict | UpdateElementRequestBody
958
+ Body containing information about the status change. Supersedes other parameters.
959
+
960
+ Returns
961
+ -------
962
+ None
963
+
964
+ Raises
965
+ ------
966
+ PyegeriaException
967
+
968
+ """
969
+
970
+ validate_guid(glossary_term_guid)
971
+
972
+ if body is None:
973
+ body = {
974
+ "class": "UpdateElementRequestBody",
975
+ "contentStatus": term_status,
976
+ "mergeUpdate": True,
977
+ }
978
+ await self._async_update_glossary_term( glossary_term_guid, body)
979
+ logger.info(f"Updated term status {glossary_term_guid}")
980
+
981
+
982
+ @dynamic_catch
983
+ def update_glossary_term_status(
984
+ self,
985
+ glossary_term_guid: str, term_status: str = "DRAFT",
986
+ body: Optional[dict | UpdateElementRequestBody] = None,
987
+ ) -> None:
988
+ """Add the data field values classification to a glossary term
989
+
990
+ Async Version.
991
+
992
+ Parameters
993
+ ----------
994
+ glossary_term_guid: str
995
+ Unique identifier for the source glossary term.
996
+ term_status: str
997
+ new status of the term.
998
+ body: dict | UpdateStatusRequestBody
999
+ Body containing information about the status change. Supersedes other parameters.
1000
+
1001
+ Returns
1002
+ -------
1003
+ None
1004
+
1005
+ Raises
1006
+ ------
1007
+ PyegeriaException
1008
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1009
+ PyegeriaAPIException
1010
+ Raised by the server when an issue arises in processing a valid request.
1011
+ NotAuthoclearizedException
1012
+ The principle specified by the user_id does not have authorization for the requested action.
1013
+ Notes
1014
+ -----
1015
+ An example body is:
1016
+
1017
+ {
1018
+ "class" : "UpdateStatusRequestBody",
1019
+ "newStatus" : "DRAFT"
1020
+ }
1021
+
1022
+ """
1023
+ loop = asyncio.get_event_loop()
1024
+ loop.run_until_complete(
1025
+ self._async_update_glossary_term_status(
1026
+ glossary_term_guid,
1027
+ body,
1028
+ )
1029
+ )
1030
+
1031
+ @dynamic_catch
1032
+ async def _async_delete_term(
1033
+ self,
1034
+ term_guid: str,
1035
+ cascade: bool = False,
1036
+ body: Optional[dict | DeleteElementRequestBody] = None
1037
+ ) -> None:
1038
+ """Delete the glossary terms associated with the specified glossary. Async version.
1039
+
1040
+ Parameters
1041
+ ----------
1042
+ term_guid : str,
1043
+ The unique identifier for the term to delete.
1044
+ for_lineage: bool, opt, default = False
1045
+ Set true for lineage processing - generally false.
1046
+ for_duplicate_processing: bool, opt, default = False
1047
+ Set true if duplicate processing handled externally - generally set False.
1048
+
1049
+ Returns
1050
+ -------
1051
+ None
1052
+
1053
+ Raises
1054
+ ------
1055
+ PyegeriaInvalidParameterException
1056
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1057
+ PyegeriaAPIException
1058
+ Raised by the server when an issue arises in processing a valid request.
1059
+ NotAuthorizedException
1060
+ The principle specified by the user_id does not have authorization for the requested action.
1061
+ Notes
1062
+ -----
1063
+ """
1064
+
1065
+ validate_guid(term_guid)
1066
+
1067
+ url = (
1068
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1069
+ f"terms/{term_guid}/delete"
1070
+ )
1071
+ await self._async_delete_element_request(url, body, cascade)
1072
+ logger.info(f"Deleted collection {term_guid} with cascade {cascade}")
1073
+
1074
+
1075
+ def delete_term(
1076
+ self,
1077
+ term_guid: str,
1078
+ cascade: bool = False,
1079
+ body: Optional[dict | DeleteElementRequestBody] = None
1080
+ ) -> None:
1081
+ """Delete the glossary terms associated with the specified glossary.
1082
+
1083
+ Parameters
1084
+ ----------
1085
+ term_guid : str,
1086
+ The unique identifier for the term to delete.
1087
+ for_lineage: bool, opt, default = False
1088
+ Set true for lineage processing - generally false.
1089
+ for_duplicate_processing: bool, opt, default = False
1090
+ Set true if duplicate processing handled externally - generally set False.
1091
+
1092
+ Returns
1093
+ -------
1094
+ None
1095
+
1096
+ Raises
1097
+ ------
1098
+ PyegeriaInvalidParameterException
1099
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1100
+ PyegeriaAPIException
1101
+ Raised by the server when an issue arises in processing a valid request.
1102
+ NotAuthorizedException
1103
+ The principle specified by the user_id does not have authorization for the requested action.
1104
+ Notes
1105
+ -----
1106
+ """
1107
+ loop = asyncio.get_event_loop()
1108
+ loop.run_until_complete(
1109
+ self._async_delete_term(term_guid, cascade, body)
1110
+ )
1111
+
1112
+ async def _async_move_term(
1113
+ self,
1114
+ term_guid: str,
1115
+ glossary_guid: str,
1116
+ body: Optional[dict | DeleteRelationshipRequestBody] = None
1117
+ ) -> None:
1118
+ """Move the glossary terms to the specified glossary. Async version.
1119
+
1120
+ Parameters
1121
+ ----------
1122
+ term_guid : str,
1123
+ The unique identifier for the term to delete.
1124
+
1125
+
1126
+ Returns
1127
+ -------
1128
+ None
1129
+
1130
+ Raises
1131
+ ------
1132
+ PyegeriaInvalidParameterException
1133
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1134
+ PyegeriaAPIException
1135
+ Raised by the server when an issue arises in processing a valid request.
1136
+ NotAuthorizedException
1137
+ The principle specified by the user_id does not have authorization for the requested action.
1138
+ Notes
1139
+ -----
1140
+ """
1141
+
1142
+ validate_guid(term_guid)
1143
+
1144
+ url = (
1145
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1146
+ f"terms/{term_guid}/move-to/{glossary_guid}"
1147
+ )
1148
+ await self._async_delete_relationship_request(url, body)
1149
+ logger.info(f"Moved collection {term_guid} to glossary {glossary_guid}")
1150
+
1151
+
1152
+ def move_term(
1153
+ self,
1154
+ term_guid: str,
1155
+ glossary_guid: str,
1156
+ body: Optional[dict | DeleteRelationshipRequestBody] = None
1157
+ ) -> None:
1158
+ """Move the glossary terms to the specified glossary.
1159
+
1160
+ Parameters
1161
+ ----------
1162
+ term_guid : str,
1163
+ The unique identifier for the term to delete.
1164
+
1165
+
1166
+ Returns
1167
+ -------
1168
+ None
1169
+
1170
+ Raises
1171
+ ------
1172
+ PyegeriaInvalidParameterException
1173
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1174
+ PyegeriaAPIException
1175
+ Raised by the server when an issue arises in processing a valid request.
1176
+ NotAuthorizedException
1177
+ The principle specified by the user_id does not have authorization for the requested action.
1178
+ Notes
1179
+ -----
1180
+ """
1181
+ loop = asyncio.get_event_loop()
1182
+ loop.run_until_complete(
1183
+ self._async_move_term(term_guid, glossary_guid, body)
1184
+ )
1185
+
1186
+
1187
+
1188
+ #
1189
+ # Categories are just Folders in collection manager
1190
+ #
1191
+
1192
+
1193
+
1194
+
1195
+ #
1196
+ # From glossary browser
1197
+ #
1198
+
1199
+
1200
+
1201
+ async def _async_add_is_abstract_concepts(
1202
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1203
+ ) -> None:
1204
+ """Add a relationship between terms. Async Version.
1205
+
1206
+ Parameters
1207
+ ----------
1208
+ term1_guid : str
1209
+ Unique identifier of the first glossary term in relationship.
1210
+ term2_guid : str
1211
+ Unique identifier of the second glossary term in relationship.
1212
+ relationship_type: str
1213
+ Type of relationship to add.
1214
+ body: dict, optional, default = None
1215
+ Further optional details for the relationship.
1216
+
1217
+
1218
+ Returns
1219
+ -------
1220
+ None
1221
+
1222
+ Raises
1223
+ ------
1224
+ PyegeriaInvalidParameterException
1225
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1226
+ PyegeriaAPIException
1227
+ Raised by the server when an issue arises in processing a valid request.
1228
+ NotAuthorizedException
1229
+ The principle specified by the user_id does not have authorization for the requested action.
1230
+
1231
+ Notes
1232
+ ----
1233
+ Body is currently required but can be empty except for class. Basic structure is:
1234
+
1235
+ {
1236
+ "class" : "NewClassificationRequestBody",
1237
+ "effectiveTime" : {{@isoTimestamp}},
1238
+ "properties" : {
1239
+ "class" : "GlossaryTermRelationship",
1240
+
1241
+ "effectiveFrom" : "{{@isoTimestamp}}",
1242
+ "effectiveTo" : "{{@isoTimestamp}}",
1243
+ "extendedProperties" : {
1244
+ }
1245
+ }
1246
+ }
1247
+ """
1248
+
1249
+ url = (
1250
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1251
+ f"terms/{term_guid}/is-abstract-concept"
1252
+ )
1253
+ if body is None:
1254
+ body = {
1255
+ "class": "NewClassificationRequestBody",
1256
+ "properties":
1257
+ {
1258
+ "class": "AbstractConceptProperties"
1259
+ }
1260
+ }
1261
+
1262
+ await self._async_new_classification_request(url, "AbstractConceptProperties", body)
1263
+ logger.info(f"Added AbstractConcept classification to {term_guid}")
1264
+
1265
+
1266
+ def add_is_abstract_concept(
1267
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1268
+ ) -> None:
1269
+ """Add a relationship between terms.
1270
+
1271
+ Parameters
1272
+ ----------
1273
+ term1_guid : str
1274
+ Unique identifier of the first glossary term in relationship.
1275
+ term2_guid : str
1276
+ Unique identifier of the second glossary term in relationship.
1277
+ relationship_type: str
1278
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1279
+ body: dict, optional, default = None
1280
+ Further optional details for the relationship.
1281
+
1282
+ Returns
1283
+ -------
1284
+ None
1285
+
1286
+ Raises
1287
+ ------
1288
+ PyegeriaInvalidParameterException
1289
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1290
+ PyegeriaAPIException
1291
+ Raised by the server when an issue arises in processing a valid request.
1292
+ NotAuthorizedException
1293
+ The principle specified by the user_id does not have authorization for the requested action.
1294
+
1295
+ Notes
1296
+ ----
1297
+ Body is currently required but can be empty except for class. Basic structure is:
1298
+
1299
+ {
1300
+ "class" : "NewRelationshipRequestBody",
1301
+ "effectiveTime" : {{@isoTimestamp}},
1302
+ "properties" : {
1303
+ "class" : "GlossaryTermRelationship",
1304
+ "expression" : "",
1305
+ "confidence" : 0,
1306
+ "description" : "",
1307
+ "status" : "",
1308
+ "steward" : "",
1309
+ "source" : "",
1310
+ "effectiveFrom" : "{{@isoTimestamp}}",
1311
+ "effectiveTo" : "{{@isoTimestamp}}",
1312
+ "extendedProperties" : {
1313
+ }
1314
+ }
1315
+ }
1316
+ """
1317
+ loop = asyncio.get_event_loop()
1318
+ loop.run_until_complete(
1319
+ self._async_add_is_abstract_concepts(term_guid, body)
1320
+ )
1321
+
1322
+ async def _async_remove_is_abstract_concepts(
1323
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1324
+ ) -> None:
1325
+ """Add a relationship between terms. Async Version.
1326
+
1327
+ Parameters
1328
+ ----------
1329
+ term1_guid : str
1330
+ Unique identifier of the first glossary term in relationship.
1331
+ term2_guid : str
1332
+ Unique identifier of the second glossary term in relationship.
1333
+ relationship_type: str
1334
+ Type of relationship to add.
1335
+ body: dict, optional, default = None
1336
+ Further optional details for the relationship.
1337
+
1338
+
1339
+ Returns
1340
+ -------
1341
+ None
1342
+
1343
+ Raises
1344
+ ------
1345
+ PyegeriaInvalidParameterException
1346
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1347
+ PyegeriaAPIException
1348
+ Raised by the server when an issue arises in processing a valid request.
1349
+ NotAuthorizedException
1350
+ The principle specified by the user_id does not have authorization for the requested action.
1351
+
1352
+ Notes
1353
+ ----
1354
+ Body is currently required but can be empty except for class. Basic structure is:
1355
+
1356
+ {
1357
+ "class" : "NewClassificationRequestBody",
1358
+ "effectiveTime" : {{@isoTimestamp}},
1359
+ "properties" : {
1360
+ "class" : "GlossaryTermRelationship",
1361
+
1362
+ "effectiveFrom" : "{{@isoTimestamp}}",
1363
+ "effectiveTo" : "{{@isoTimestamp}}",
1364
+ "extendedProperties" : {
1365
+ }
1366
+ }
1367
+ }
1368
+ """
1369
+
1370
+ url = (
1371
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1372
+ f"terms/{term_guid}/is-abstract-concept/remove"
1373
+ )
1374
+ await self._async_delete_classification_request(url, body)
1375
+ logger.info(f"Removed AbstractConcept classification to {term_guid}")
1376
+
1377
+ def remove_is_abstract_concept(
1378
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1379
+ ) -> None:
1380
+ """Add a relationship between terms.
1381
+
1382
+ Parameters
1383
+ ----------
1384
+ term1_guid : str
1385
+ Unique identifier of the first glossary term in relationship.
1386
+ term2_guid : str
1387
+ Unique identifier of the second glossary term in relationship.
1388
+ relationship_type: str
1389
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1390
+ body: dict, optional, default = None
1391
+ Further optional details for the relationship.
1392
+
1393
+ Returns
1394
+ -------
1395
+ None
1396
+
1397
+ Raises
1398
+ ------
1399
+ PyegeriaInvalidParameterException
1400
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1401
+ PyegeriaAPIException
1402
+ Raised by the server when an issue arises in processing a valid request.
1403
+ NotAuthorizedException
1404
+ The principle specified by the user_id does not have authorization for the requested action.
1405
+
1406
+ Notes
1407
+ ----
1408
+ Body is currently required but can be empty except for class. Basic structure is:
1409
+
1410
+ {
1411
+ "class" : "NewRelationshipRequestBody",
1412
+ "effectiveTime" : {{@isoTimestamp}},
1413
+ "properties" : {
1414
+ "class" : "GlossaryTermRelationship",
1415
+ "expression" : "",
1416
+ "confidence" : 0,
1417
+ "description" : "",
1418
+ "status" : "",
1419
+ "steward" : "",
1420
+ "source" : "",
1421
+ "effectiveFrom" : "{{@isoTimestamp}}",
1422
+ "effectiveTo" : "{{@isoTimestamp}}",
1423
+ "extendedProperties" : {
1424
+ }
1425
+ }
1426
+ }
1427
+ """
1428
+ loop = asyncio.get_event_loop()
1429
+ loop.run_until_complete(
1430
+ self._async_remove_is_abstract_concepts(term_guid, body)
1431
+ )
1432
+
1433
+
1434
+ async def _async_add_is_context_definition(
1435
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1436
+ ) -> None:
1437
+ """Add a relationship between terms. Async Version.
1438
+
1439
+ Parameters
1440
+ ----------
1441
+ term1_guid : str
1442
+ Unique identifier of the first glossary term in relationship.
1443
+ term2_guid : str
1444
+ Unique identifier of the second glossary term in relationship.
1445
+ relationship_type: str
1446
+ Type of relationship to add.
1447
+ body: dict, optional, default = None
1448
+ Further optional details for the relationship.
1449
+
1450
+
1451
+ Returns
1452
+ -------
1453
+ None
1454
+
1455
+ Raises
1456
+ ------
1457
+ PyegeriaInvalidParameterException
1458
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1459
+ PyegeriaAPIException
1460
+ Raised by the server when an issue arises in processing a valid request.
1461
+ NotAuthorizedException
1462
+ The principle specified by the user_id does not have authorization for the requested action.
1463
+
1464
+ Notes
1465
+ ----
1466
+ Body is currently required but can be empty except for class. Basic structure is:
1467
+
1468
+ {
1469
+ "class" : "NewClassificationRequestBody",
1470
+ "effectiveTime" : {{@isoTimestamp}},
1471
+ "properties" : {
1472
+ "class" : "GlossaryTermRelationship",
1473
+
1474
+ "effectiveFrom" : "{{@isoTimestamp}}",
1475
+ "effectiveTo" : "{{@isoTimestamp}}",
1476
+ "extendedProperties" : {
1477
+ }
1478
+ }
1479
+ }
1480
+ """
1481
+
1482
+ url = (
1483
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1484
+ f"terms/{term_guid}/is-context-definition"
1485
+ )
1486
+ if body is None:
1487
+ body = {
1488
+ "class": "NewClassificationRequestBody",
1489
+ "properties":
1490
+ {
1491
+ "class": "ContextDefinitionProperties"
1492
+ }
1493
+ }
1494
+
1495
+ await self._async_new_classification_request(url, "ContextDefinitionProperties", body)
1496
+ logger.info(f"Added AbstractConcept classification to {term_guid}")
1497
+
1498
+
1499
+
1500
+ def add_is_context_definition(
1501
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1502
+ ) -> None:
1503
+ """Add a relationship between terms.
1504
+
1505
+ Parameters
1506
+ ----------
1507
+ term1_guid : str
1508
+ Unique identifier of the first glossary term in relationship.
1509
+ term2_guid : str
1510
+ Unique identifier of the second glossary term in relationship.
1511
+ relationship_type: str
1512
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1513
+ body: dict, optional, default = None
1514
+ Further optional details for the relationship.
1515
+
1516
+ Returns
1517
+ -------
1518
+ None
1519
+
1520
+ Raises
1521
+ ------
1522
+ PyegeriaInvalidParameterException
1523
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1524
+ PyegeriaAPIException
1525
+ Raised by the server when an issue arises in processing a valid request.
1526
+ NotAuthorizedException
1527
+ The principle specified by the user_id does not have authorization for the requested action.
1528
+
1529
+ Notes
1530
+ ----
1531
+ Body is currently required but can be empty except for class. Basic structure is:
1532
+
1533
+ {
1534
+ "class" : "NewRelationshipRequestBody",
1535
+ "effectiveTime" : {{@isoTimestamp}},
1536
+ "properties" : {
1537
+ "class" : "GlossaryTermRelationship",
1538
+ "expression" : "",
1539
+ "confidence" : 0,
1540
+ "description" : "",
1541
+ "status" : "",
1542
+ "steward" : "",
1543
+ "source" : "",
1544
+ "effectiveFrom" : "{{@isoTimestamp}}",
1545
+ "effectiveTo" : "{{@isoTimestamp}}",
1546
+ "extendedProperties" : {
1547
+ }
1548
+ }
1549
+ }
1550
+ """
1551
+ loop = asyncio.get_event_loop()
1552
+ loop.run_until_complete(
1553
+ self._async_add_is_context_definition(term_guid, body)
1554
+ )
1555
+
1556
+ async def _async_remove_is_context_definition(
1557
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1558
+ ) -> None:
1559
+ """Add a relationship between terms. Async Version.
1560
+
1561
+ Parameters
1562
+ ----------
1563
+ term1_guid : str
1564
+ Unique identifier of the first glossary term in relationship.
1565
+ term2_guid : str
1566
+ Unique identifier of the second glossary term in relationship.
1567
+ relationship_type: str
1568
+ Type of relationship to add.
1569
+ body: dict, optional, default = None
1570
+ Further optional details for the relationship.
1571
+
1572
+
1573
+ Returns
1574
+ -------
1575
+ None
1576
+
1577
+ Raises
1578
+ ------
1579
+ PyegeriaInvalidParameterException
1580
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1581
+ PyegeriaAPIException
1582
+ Raised by the server when an issue arises in processing a valid request.
1583
+ NotAuthorizedException
1584
+ The principle specified by the user_id does not have authorization for the requested action.
1585
+
1586
+ Notes
1587
+ ----
1588
+ Body is currently required but can be empty except for class. Basic structure is:
1589
+
1590
+ {
1591
+ "class" : "NewClassificationRequestBody",
1592
+ "effectiveTime" : {{@isoTimestamp}},
1593
+ "properties" : {
1594
+ "class" : "GlossaryTermRelationship",
1595
+
1596
+ "effectiveFrom" : "{{@isoTimestamp}}",
1597
+ "effectiveTo" : "{{@isoTimestamp}}",
1598
+ "extendedProperties" : {
1599
+ }
1600
+ }
1601
+ }
1602
+ """
1603
+
1604
+ url = (
1605
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1606
+ f"terms/{term_guid}/is-context-definition/remove"
1607
+ )
1608
+ await self._async_delete_classification_request(url, body)
1609
+ logger.info(f"Removed ContextDefinition classification to {term_guid}")
1610
+
1611
+ def remove_is_context_definition(
1612
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1613
+ ) -> None:
1614
+ """Add a relationship between terms.
1615
+
1616
+ Parameters
1617
+ ----------
1618
+ term1_guid : str
1619
+ Unique identifier of the first glossary term in relationship.
1620
+ term2_guid : str
1621
+ Unique identifier of the second glossary term in relationship.
1622
+ relationship_type: str
1623
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1624
+ body: dict, optional, default = None
1625
+ Further optional details for the relationship.
1626
+
1627
+ Returns
1628
+ -------
1629
+ None
1630
+
1631
+ Raises
1632
+ ------
1633
+ PyegeriaInvalidParameterException
1634
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1635
+ PyegeriaAPIException
1636
+ Raised by the server when an issue arises in processing a valid request.
1637
+ NotAuthorizedException
1638
+ The principle specified by the user_id does not have authorization for the requested action.
1639
+
1640
+ Notes
1641
+ ----
1642
+ Body is currently required but can be empty except for class. Basic structure is:
1643
+
1644
+ {
1645
+ "class" : "NewRelationshipRequestBody",
1646
+ "effectiveTime" : {{@isoTimestamp}},
1647
+ "properties" : {
1648
+ "class" : "GlossaryTermRelationship",
1649
+ "expression" : "",
1650
+ "confidence" : 0,
1651
+ "description" : "",
1652
+ "status" : "",
1653
+ "steward" : "",
1654
+ "source" : "",
1655
+ "effectiveFrom" : "{{@isoTimestamp}}",
1656
+ "effectiveTo" : "{{@isoTimestamp}}",
1657
+ "extendedProperties" : {
1658
+ }
1659
+ }
1660
+ }
1661
+ """
1662
+ loop = asyncio.get_event_loop()
1663
+ loop.run_until_complete(
1664
+ self._async_remove_is_context_definition(term_guid, body)
1665
+ )
1666
+
1667
+
1668
+ async def _async_add_is_data_value(
1669
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1670
+ ) -> None:
1671
+ """Add a relationship between terms. Async Version.
1672
+
1673
+ Parameters
1674
+ ----------
1675
+ term1_guid : str
1676
+ Unique identifier of the first glossary term in relationship.
1677
+ term2_guid : str
1678
+ Unique identifier of the second glossary term in relationship.
1679
+ relationship_type: str
1680
+ Type of relationship to add.
1681
+ body: dict, optional, default = None
1682
+ Further optional details for the relationship.
1683
+
1684
+
1685
+ Returns
1686
+ -------
1687
+ None
1688
+
1689
+ Raises
1690
+ ------
1691
+ PyegeriaInvalidParameterException
1692
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1693
+ PyegeriaAPIException
1694
+ Raised by the server when an issue arises in processing a valid request.
1695
+ NotAuthorizedException
1696
+ The principle specified by the user_id does not have authorization for the requested action.
1697
+
1698
+ Notes
1699
+ ----
1700
+ Body is currently required but can be empty except for class. Basic structure is:
1701
+
1702
+ {
1703
+ "class" : "NewClassificationRequestBody",
1704
+ "effectiveTime" : {{@isoTimestamp}},
1705
+ "properties" : {
1706
+ "class" : "GlossaryTermRelationship",
1707
+
1708
+ "effectiveFrom" : "{{@isoTimestamp}}",
1709
+ "effectiveTo" : "{{@isoTimestamp}}",
1710
+ "extendedProperties" : {
1711
+ }
1712
+ }
1713
+ }
1714
+ """
1715
+
1716
+ url = (
1717
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1718
+ f"terms/{term_guid}/is-data-value"
1719
+ )
1720
+ if body is None:
1721
+ body = {
1722
+ "class": "NewClassificationRequestBody",
1723
+ "properties":
1724
+ {
1725
+ "class": "DataValueProperties"
1726
+ }
1727
+ }
1728
+
1729
+ await self._async_new_classification_request(url, "DataValueProperties", body)
1730
+ logger.info(f"Added DataValue classification to {term_guid}")
1731
+
1732
+
1733
+
1734
+ def add_is_data_value(
1735
+ self, term_guid: str, body: Optional[dict | NewClassificationRequestBody] = None,
1736
+ ) -> None:
1737
+ """Add a relationship between terms.
1738
+
1739
+ Parameters
1740
+ ----------
1741
+ term1_guid : str
1742
+ Unique identifier of the first glossary term in relationship.
1743
+ term2_guid : str
1744
+ Unique identifier of the second glossary term in relationship.
1745
+ relationship_type: str
1746
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1747
+ body: dict, optional, default = None
1748
+ Further optional details for the relationship.
1749
+
1750
+ Returns
1751
+ -------
1752
+ None
1753
+
1754
+ Raises
1755
+ ------
1756
+ PyegeriaInvalidParameterException
1757
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1758
+ PyegeriaAPIException
1759
+ Raised by the server when an issue arises in processing a valid request.
1760
+ NotAuthorizedException
1761
+ The principle specified by the user_id does not have authorization for the requested action.
1762
+
1763
+ Notes
1764
+ ----
1765
+ Body is currently required but can be empty except for class. Basic structure is:
1766
+
1767
+ {
1768
+ "class" : "NewRelationshipRequestBody",
1769
+ "effectiveTime" : {{@isoTimestamp}},
1770
+ "properties" : {
1771
+ "class" : "GlossaryTermRelationship",
1772
+ "expression" : "",
1773
+ "confidence" : 0,
1774
+ "description" : "",
1775
+ "status" : "",
1776
+ "steward" : "",
1777
+ "source" : "",
1778
+ "effectiveFrom" : "{{@isoTimestamp}}",
1779
+ "effectiveTo" : "{{@isoTimestamp}}",
1780
+ "extendedProperties" : {
1781
+ }
1782
+ }
1783
+ }
1784
+ """
1785
+ loop = asyncio.get_event_loop()
1786
+ loop.run_until_complete(
1787
+ self._async_add_is_data_value(term_guid, body)
1788
+ )
1789
+
1790
+ async def _async_remove_is_data_value(
1791
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1792
+ ) -> None:
1793
+ """Add a relationship between terms. Async Version.
1794
+
1795
+ Parameters
1796
+ ----------
1797
+ term1_guid : str
1798
+ Unique identifier of the first glossary term in relationship.
1799
+ term2_guid : str
1800
+ Unique identifier of the second glossary term in relationship.
1801
+ relationship_type: str
1802
+ Type of relationship to add.
1803
+ body: dict, optional, default = None
1804
+ Further optional details for the relationship.
1805
+
1806
+
1807
+ Returns
1808
+ -------
1809
+ None
1810
+
1811
+ Raises
1812
+ ------
1813
+ PyegeriaInvalidParameterException
1814
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1815
+ PyegeriaAPIException
1816
+ Raised by the server when an issue arises in processing a valid request.
1817
+ NotAuthorizedException
1818
+ The principle specified by the user_id does not have authorization for the requested action.
1819
+
1820
+ Notes
1821
+ ----
1822
+ Body is currently required but can be empty except for class. Basic structure is:
1823
+
1824
+ {
1825
+ "class" : "NewClassificationRequestBody",
1826
+ "effectiveTime" : {{@isoTimestamp}},
1827
+ "properties" : {
1828
+ "class" : "GlossaryTermRelationship",
1829
+
1830
+ "effectiveFrom" : "{{@isoTimestamp}}",
1831
+ "effectiveTo" : "{{@isoTimestamp}}",
1832
+ "extendedProperties" : {
1833
+ }
1834
+ }
1835
+ }
1836
+ """
1837
+
1838
+ url = (
1839
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1840
+ f"terms/{term_guid}/is-data-value/remove"
1841
+ )
1842
+ await self._async_delete_classification_request(url, body)
1843
+ logger.info(f"Removed DataValue classification to {term_guid}")
1844
+
1845
+ def remove_is_data_value(
1846
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
1847
+ ) -> None:
1848
+ """Add a relationship between terms.
1849
+
1850
+ Parameters
1851
+ ----------
1852
+ term1_guid : str
1853
+ Unique identifier of the first glossary term in relationship.
1854
+ term2_guid : str
1855
+ Unique identifier of the second glossary term in relationship.
1856
+ relationship_type: str
1857
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1858
+ body: dict, optional, default = None
1859
+ Further optional details for the relationship.
1860
+
1861
+ Returns
1862
+ -------
1863
+ None
1864
+
1865
+ Raises
1866
+ ------
1867
+ PyegeriaInvalidParameterException
1868
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1869
+ PyegeriaAPIException
1870
+ Raised by the server when an issue arises in processing a valid request.
1871
+ NotAuthorizedException
1872
+ The principle specified by the user_id does not have authorization for the requested action.
1873
+
1874
+ Notes
1875
+ ----
1876
+ Body is currently required but can be empty except for class. Basic structure is:
1877
+
1878
+ {
1879
+ "class" : "NewRelationshipRequestBody",
1880
+ "effectiveTime" : {{@isoTimestamp}},
1881
+ "properties" : {
1882
+ "class" : "GlossaryTermRelationship",
1883
+ "expression" : "",
1884
+ "confidence" : 0,
1885
+ "description" : "",
1886
+ "status" : "",
1887
+ "steward" : "",
1888
+ "source" : "",
1889
+ "effectiveFrom" : "{{@isoTimestamp}}",
1890
+ "effectiveTo" : "{{@isoTimestamp}}",
1891
+ "extendedProperties" : {
1892
+ }
1893
+ }
1894
+ }
1895
+ """
1896
+ loop = asyncio.get_event_loop()
1897
+ loop.run_until_complete(
1898
+ self._async_remove_is_data_value(term_guid, body)
1899
+ )
1900
+
1901
+
1902
+ async def _async_add_activity_description(
1903
+ self, term_guid: str, activity_type: int = None, body: Optional[dict | NewClassificationRequestBody] = None,
1904
+ ) -> None:
1905
+ """Add a relationship between terms. Async Version.
1906
+
1907
+ Parameters
1908
+ ----------
1909
+ term1_guid : str
1910
+ Unique identifier of the first glossary term in relationship.
1911
+ term2_guid : str
1912
+ Unique identifier of the second glossary term in relationship.
1913
+ relationship_type: str
1914
+ Type of relationship to add.
1915
+ body: dict, optional, default = None
1916
+ Further optional details for the relationship.
1917
+
1918
+
1919
+ Returns
1920
+ -------
1921
+ None
1922
+
1923
+ Raises
1924
+ ------
1925
+ PyegeriaInvalidParameterException
1926
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1927
+ PyegeriaAPIException
1928
+ Raised by the server when an issue arises in processing a valid request.
1929
+ NotAuthorizedException
1930
+ The principle specified by the user_id does not have authorization for the requested action.
1931
+
1932
+ Notes
1933
+ ----
1934
+ Body is currently required but can be empty except for class. Basic structure is:
1935
+
1936
+ {
1937
+ "class" : "NewClassificationRequestBody",
1938
+ "effectiveTime" : {{@isoTimestamp}},
1939
+ "properties" : {
1940
+ "class" : "GlossaryTermRelationship",
1941
+
1942
+ "effectiveFrom" : "{{@isoTimestamp}}",
1943
+ "effectiveTo" : "{{@isoTimestamp}}",
1944
+ "extendedProperties" : {
1945
+ }
1946
+ }
1947
+ }
1948
+ """
1949
+
1950
+ if body is None:
1951
+ body = {
1952
+ "class": "NewClassificationRequestBody",
1953
+ "properties": {
1954
+ "class": "ActivityDescriptionProperties",
1955
+ "type": activity_type,
1956
+ }
1957
+ }
1958
+
1959
+ url = (
1960
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
1961
+ f"terms/{term_guid}/is-activity"
1962
+ )
1963
+ await self._async_new_classification_request(url, "ActivityDescriptionProperties", body)
1964
+ logger.info(f"Added DataValue classification to {term_guid}")
1965
+
1966
+
1967
+
1968
+ def add_activity_description(
1969
+ self, term_guid: str, activity_type: int = None, body: Optional[dict | NewClassificationRequestBody] = None,
1970
+ ) -> None:
1971
+ """Add a relationship between terms.
1972
+
1973
+ Parameters
1974
+ ----------
1975
+ term1_guid : str
1976
+ Unique identifier of the first glossary term in relationship.
1977
+ term2_guid : str
1978
+ Unique identifier of the second glossary term in relationship.
1979
+ relationship_type: str
1980
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
1981
+ body: dict, optional, default = None
1982
+ Further optional details for the relationship.
1983
+
1984
+ Returns
1985
+ -------
1986
+ None
1987
+
1988
+ Raises
1989
+ ------
1990
+ PyegeriaInvalidParameterException
1991
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
1992
+ PyegeriaAPIException
1993
+ Raised by the server when an issue arises in processing a valid request.
1994
+ NotAuthorizedException
1995
+ The principle specified by the user_id does not have authorization for the requested action.
1996
+
1997
+ Notes
1998
+ ----
1999
+ Body is currently required but can be empty except for class. Basic structure is:
2000
+
2001
+ {
2002
+ "class" : "NewRelationshipRequestBody",
2003
+ "effectiveTime" : {{@isoTimestamp}},
2004
+ "properties" : {
2005
+ "class" : "GlossaryTermRelationship",
2006
+ "expression" : "",
2007
+ "confidence" : 0,
2008
+ "description" : "",
2009
+ "status" : "",
2010
+ "steward" : "",
2011
+ "source" : "",
2012
+ "effectiveFrom" : "{{@isoTimestamp}}",
2013
+ "effectiveTo" : "{{@isoTimestamp}}",
2014
+ "extendedProperties" : {
2015
+ }
2016
+ }
2017
+ }
2018
+ """
2019
+ loop = asyncio.get_event_loop()
2020
+ loop.run_until_complete(
2021
+ self._async_add_activity_description(term_guid, activity_type, body)
2022
+ )
2023
+
2024
+ async def _async_remove_activity_description(
2025
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
2026
+ ) -> None:
2027
+ """Add a relationship between terms. Async Version.
2028
+
2029
+ Parameters
2030
+ ----------
2031
+ term1_guid : str
2032
+ Unique identifier of the first glossary term in relationship.
2033
+ term2_guid : str
2034
+ Unique identifier of the second glossary term in relationship.
2035
+ relationship_type: str
2036
+ Type of relationship to add.
2037
+ body: dict, optional, default = None
2038
+ Further optional details for the relationship.
2039
+
2040
+
2041
+ Returns
2042
+ -------
2043
+ None
2044
+
2045
+ Raises
2046
+ ------
2047
+ PyegeriaInvalidParameterException
2048
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2049
+ PyegeriaAPIException
2050
+ Raised by the server when an issue arises in processing a valid request.
2051
+ NotAuthorizedException
2052
+ The principle specified by the user_id does not have authorization for the requested action.
2053
+
2054
+ Notes
2055
+ ----
2056
+ Body is currently required but can be empty except for class. Basic structure is:
2057
+
2058
+ {
2059
+ "class" : "NewClassificationRequestBody",
2060
+ "effectiveTime" : {{@isoTimestamp}},
2061
+ "properties" : {
2062
+ "class" : "GlossaryTermRelationship",
2063
+
2064
+ "effectiveFrom" : "{{@isoTimestamp}}",
2065
+ "effectiveTo" : "{{@isoTimestamp}}",
2066
+ "extendedProperties" : {
2067
+ }
2068
+ }
2069
+ }
2070
+ """
2071
+
2072
+ url = (
2073
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
2074
+ f"terms/{term_guid}/is-activity/remove"
2075
+ )
2076
+ await self._async_delete_classification_request(url, body)
2077
+ logger.info(f"Removed ActivityDescription classification to {term_guid}")
2078
+
2079
+ def remove_activity_description(
2080
+ self, term_guid: str, body: Optional[dict | DeleteClassificationRequestBody] = None,
2081
+ ) -> None:
2082
+ """Add a relationship between terms.
2083
+
2084
+ Parameters
2085
+ ----------
2086
+ term1_guid : str
2087
+ Unique identifier of the first glossary term in relationship.
2088
+ term2_guid : str
2089
+ Unique identifier of the second glossary term in relationship.
2090
+ relationship_type: str
2091
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
2092
+ body: dict, optional, default = None
2093
+ Further optional details for the relationship.
2094
+
2095
+ Returns
2096
+ -------
2097
+ None
2098
+
2099
+ Raises
2100
+ ------
2101
+ PyegeriaInvalidParameterException
2102
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2103
+ PyegeriaAPIException
2104
+ Raised by the server when an issue arises in processing a valid request.
2105
+ NotAuthorizedException
2106
+ The principle specified by the user_id does not have authorization for the requested action.
2107
+
2108
+ Notes
2109
+ ----
2110
+ Body is currently required but can be empty except for class. Basic structure is:
2111
+
2112
+ {
2113
+ "class" : "NewRelationshipRequestBody",
2114
+ "effectiveTime" : {{@isoTimestamp}},
2115
+ "properties" : {
2116
+ "class" : "GlossaryTermRelationship",
2117
+ "expression" : "",
2118
+ "confidence" : 0,
2119
+ "description" : "",
2120
+ "status" : "",
2121
+ "steward" : "",
2122
+ "source" : "",
2123
+ "effectiveFrom" : "{{@isoTimestamp}}",
2124
+ "effectiveTo" : "{{@isoTimestamp}}",
2125
+ "extendedProperties" : {
2126
+ }
2127
+ }
2128
+ }
2129
+ """
2130
+ loop = asyncio.get_event_loop()
2131
+ loop.run_until_complete(
2132
+ self._async_remove_activity_description(term_guid, body)
2133
+ )
2134
+
2135
+ #
2136
+ # Term - Term Relationships
2137
+ #
2138
+
2139
+ async def _async_add_relationship_between_terms(
2140
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | NewRelationshipRequestBody] = None,
2141
+ ) -> None:
2142
+ """Add a relationship between terms. Async Version.
2143
+
2144
+ Parameters
2145
+ ----------
2146
+ term1_guid : str
2147
+ Unique identifier of the first glossary term in relationship.
2148
+ term2_guid : str
2149
+ Unique identifier of the second glossary term in relationship.
2150
+ relationship_type: str
2151
+ Type of relationship to add.
2152
+ body: dict, optional, default = None
2153
+ Further optional details for the relationship.
2154
+
2155
+
2156
+ Returns
2157
+ -------
2158
+ None
2159
+
2160
+ Raises
2161
+ ------
2162
+ PyegeriaInvalidParameterException
2163
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2164
+ PyegeriaAPIException
2165
+ Raised by the server when an issue arises in processing a valid request.
2166
+ NotAuthorizedException
2167
+ The principle specified by the user_id does not have authorization for the requested action.
2168
+
2169
+ Notes
2170
+ ----
2171
+ Body is currently required but can be empty except for class. Basic structure is:
2172
+
2173
+ {
2174
+ "class" : "NewRelationshipRequestBody",
2175
+ "effectiveTime" : {{@isoTimestamp}},
2176
+ "properties" : {
2177
+ "class" : "GlossaryTermRelationship",
2178
+ "expression" : "",
2179
+ "confidence" : 0,
2180
+ "description" : "",
2181
+ "status" : "",
2182
+ "steward" : "",
2183
+ "source" : "",
2184
+ "effectiveFrom" : "{{@isoTimestamp}}",
2185
+ "effectiveTo" : "{{@isoTimestamp}}",
2186
+ "extendedProperties" : {
2187
+ }
2188
+ }
2189
+ }
2190
+ """
2191
+
2192
+ validate_guid(term1_guid)
2193
+ validate_guid(term2_guid)
2194
+
2195
+ if body is None:
2196
+ body = {
2197
+ "class": "NewRelationshipRequestBody",
2198
+ "properties":
2199
+ {"class": "GlossaryTermRelationship" }
2200
+ }
2201
+
2202
+
2203
+
2204
+ url = (
2205
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
2206
+ f"terms/{term1_guid}/relationships/{relationship_type}/terms/{term2_guid}"
2207
+ )
2208
+ await self._async_new_relationship_request(url, ["GlossaryTermRelationship"],body)
2209
+ logger.info(f"Added relationship between {term1_guid} and {term2_guid} of type {relationship_type}")
2210
+
2211
+ def add_relationship_between_terms(
2212
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | NewRelationshipRequestBody] = None,
2213
+ ) -> None:
2214
+ """Add a relationship between terms.
2215
+
2216
+ Parameters
2217
+ ----------
2218
+ term1_guid : str
2219
+ Unique identifier of the first glossary term in relationship.
2220
+ term2_guid : str
2221
+ Unique identifier of the second glossary term in relationship.
2222
+ relationship_type: str
2223
+ Type of relationship to add. A list of relationship types can be found using get_term_relationship_types().
2224
+ body: dict, optional, default = None
2225
+ Further optional details for the relationship.
2226
+
2227
+ Returns
2228
+ -------
2229
+ None
2230
+
2231
+ Raises
2232
+ ------
2233
+ PyegeriaInvalidParameterException
2234
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2235
+ PyegeriaAPIException
2236
+ Raised by the server when an issue arises in processing a valid request.
2237
+ NotAuthorizedException
2238
+ The principle specified by the user_id does not have authorization for the requested action.
2239
+
2240
+ Notes
2241
+ ----
2242
+ Body is currently required but can be empty except for class. Basic structure is:
2243
+
2244
+ {
2245
+ "class" : "NewRelationshipRequestBody",
2246
+ "effectiveTime" : {{@isoTimestamp}},
2247
+ "properties" : {
2248
+ "class" : "GlossaryTermRelationship",
2249
+ "expression" : "",
2250
+ "confidence" : 0,
2251
+ "description" : "",
2252
+ "status" : "",
2253
+ "steward" : "",
2254
+ "source" : "",
2255
+ "effectiveFrom" : "{{@isoTimestamp}}",
2256
+ "effectiveTo" : "{{@isoTimestamp}}",
2257
+ "extendedProperties" : {
2258
+ }
2259
+ }
2260
+ }
2261
+ """
2262
+ loop = asyncio.get_event_loop()
2263
+ loop.run_until_complete(
2264
+ self._async_add_relationship_between_terms(term1_guid, term2_guid, relationship_type,
2265
+ body)
2266
+ )
2267
+
2268
+ async def _async_update_relationship_between_terms(
2269
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | UpdateRelationshipRequestBody] = None
2270
+ ) -> None:
2271
+
2272
+ """Update a relationship between terms. Async Version.
2273
+
2274
+ Parameters
2275
+ ----------
2276
+ term1_guid : str
2277
+ Unique identifier of the first glossary term in relationship.
2278
+ term2_guid : str
2279
+ Unique identifier of the second glossary term in relationship.
2280
+ relationship_type: str
2281
+ Type of relationship to update.
2282
+ body: dict, optional, default = None
2283
+ Further optional details for the relationship.
2284
+
2285
+ Returns
2286
+ -------
2287
+ None
2288
+
2289
+ Raises
2290
+ ------
2291
+ PyegeriaInvalidParameterException
2292
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2293
+ PyegeriaAPIException
2294
+ Raised by the server when an issue arises in processing a valid request.
2295
+ NotAuthorizedException
2296
+ The principle specified by the user_id does not have authorization for the requested action.
2297
+
2298
+ Notes
2299
+ ----
2300
+ Body is currently required but can be empty except for class. Basic structure is:
2301
+
2302
+ {
2303
+ "class" : "UpdateRelationshipRequestBody",
2304
+ "effectiveTime" : {{@isoTimestamp}},
2305
+ "properties" : {
2306
+ "class" : "GlossaryTermRelationship",
2307
+ "expression" : "",
2308
+ "confidence" : 0,
2309
+ "description" : "",
2310
+ "status" : "",
2311
+ "steward" : "",
2312
+ "source" : "",
2313
+ "effectiveFrom" : "{{@isoTimestamp}}",
2314
+ "effectiveTo" : "{{@isoTimestamp}}",
2315
+ "extendedProperties" : {
2316
+ }
2317
+ }
2318
+ }
2319
+ """
2320
+
2321
+ validate_guid(term1_guid)
2322
+ validate_guid(term2_guid)
2323
+
2324
+
2325
+
2326
+ url = (
2327
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
2328
+ f"terms/{term1_guid}/relationships/{relationship_type}/terms/{term2_guid}/update")
2329
+
2330
+ await self._async_update_relationship_request(url, "GlossaryTermRelationship", body)
2331
+ logger.info(f"Updated relationship between {term1_guid} and {term2_guid} of type {relationship_type}")
2332
+
2333
+ def update_relationship_between_terms(
2334
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | UpdateRelationshipRequestBody] = None
2335
+ ) -> None:
2336
+ """Update a relationship between terms.
2337
+
2338
+ Parameters
2339
+ ----------
2340
+ term1_guid : str
2341
+ Unique identifier of the first glossary term in relationship.
2342
+ term2_guid : str
2343
+ Unique identifier of the second glossary term in relationship.
2344
+ relationship_type: str
2345
+ Type of relationship to update. A list of relationship types can be found using
2346
+ get_term_relationship_types().
2347
+ body: dict
2348
+ Details of the relationship to update.
2349
+
2350
+ Returns
2351
+ -------
2352
+ None
2353
+
2354
+ Raises
2355
+ ------
2356
+ PyegeriaInvalidParameterException
2357
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2358
+ PyegeriaAPIException
2359
+ Raised by the server when an issue arises in processing a valid request.
2360
+ NotAuthorizedException
2361
+ The principle specified by the user_id does not have authorization for the requested action.
2362
+
2363
+ Notes
2364
+ ----
2365
+ Body is currently required but can be empty except for class. Basic structure is:
2366
+
2367
+ {
2368
+ "class" : "UpdateRelationshipRequestBody",
2369
+ "effectiveTime" : {{@isoTimestamp}},
2370
+ "properties" : {
2371
+ "class" : "GlossaryTermRelationship",
2372
+ "expression" : "",
2373
+ "confidence" : 0,
2374
+ "description" : "",
2375
+ "status" : "",
2376
+ "steward" : "",
2377
+ "source" : "",
2378
+ "effectiveFrom" : "{{@isoTimestamp}}",
2379
+ "effectiveTo" : "{{@isoTimestamp}}",
2380
+ "extendedProperties" : {
2381
+ }
2382
+ }
2383
+ }
2384
+ """
2385
+ loop = asyncio.get_event_loop()
2386
+ loop.run_until_complete(
2387
+ self._async_update_relationship_between_terms(term1_guid, term2_guid, relationship_type,
2388
+ body)
2389
+ )
2390
+
2391
+ async def _async_remove_relationship_between_terms(
2392
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | DeleteRelationshipRequestBody] = None,
2393
+ ) -> None:
2394
+ """Remove a relationship between terms. Async Version.
2395
+
2396
+ Parameters
2397
+ ----------
2398
+ term1_guid : str
2399
+ Unique identifier of the first glossary term in relationship.
2400
+ term2_guid : str
2401
+ Unique identifier of the second glossary term in relationship.
2402
+ relationship_type: str
2403
+ Type of relationship to add.
2404
+ effective_time: str, optional, default = None
2405
+ Effective time to remove the relationship.
2406
+ for_lineage: bool, default is set by server
2407
+ - determines if elements classified as Memento should be returned - normally false
2408
+ for_duplicate_processing: bool, default is set by server
2409
+ - Normally false. Set true when the caller is part of a deduplication function
2410
+
2411
+ Returns
2412
+ -------
2413
+ None
2414
+
2415
+ Raises
2416
+ ------
2417
+ PyegeriaInvalidParameterException
2418
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2419
+ PyegeriaAPIException
2420
+ Raised by the server when an issue arises in processing a valid request.
2421
+ NotAuthorizedException
2422
+ The principle specified by the user_id does not have authorization for the requested action.
2423
+
2424
+
2425
+ """
2426
+
2427
+ validate_guid(term1_guid)
2428
+ validate_guid(term2_guid)
2429
+
2430
+
2431
+ url = (
2432
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
2433
+ f"terms/{term1_guid}/relationships/{relationship_type}/terms/{term2_guid}/remove"
2434
+ )
2435
+
2436
+ await self._async_delete_relationship_request(url, body)
2437
+
2438
+ def remove_relationship_between_terms(
2439
+ self, term1_guid: str, term2_guid: str, relationship_type: str, body: Optional[dict | DeleteRelationshipRequestBody] = None) -> None:
2440
+
2441
+ """Remove a relationship between terms.
2442
+
2443
+ Parameters
2444
+ ----------
2445
+ term1_guid : str
2446
+ Unique identifier of the first glossary term in relationship.
2447
+ term2_guid : str
2448
+ Unique identifier of the second glossary term in relationship.
2449
+ relationship_type: str
2450
+ Type of relationship to remove. A list of relationship types can be found using
2451
+ get_term_relationship_types().
2452
+
2453
+
2454
+ Returns
2455
+ -------
2456
+ None
2457
+
2458
+ Raises
2459
+ ------
2460
+ PyegeriaInvalidParameterException
2461
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2462
+ PyegeriaAPIException
2463
+ Raised by the server when an issue arises in processing a valid request.
2464
+ NotAuthorizedException
2465
+ The principle specified by the user_id does not have authorization for the requested action.
2466
+
2467
+ """
2468
+ loop = asyncio.get_event_loop()
2469
+ loop.run_until_complete(
2470
+ self._async_remove_relationship_between_terms(term1_guid, term2_guid, relationship_type,
2471
+ body)
2472
+ )
2473
+
2474
+ #
2475
+ # Integrated Glossary Browser methods
2476
+ #
2477
+
2478
+ def _extract_glossary_properties(self, element: dict, columns_struct: dict) -> dict:
2479
+ """Extract glossary columns for rendering.
2480
+
2481
+ This extractor uses `populate_common_columns` for standard fields (properties, header, relationships,
2482
+ subject area, mermaid). It then overlays glossary-specific values such as:
2483
+ - categories_names: comma/newline separated Display Names of categories in the glossary
2484
+ - categories_qualified_names: comma/newline separated Qualified Names of categories in the glossary
2485
+
2486
+ Parameters
2487
+ ----------
2488
+ element : dict
2489
+ Raw element as returned by the OMVS.
2490
+ columns_struct : dict
2491
+ The selected output format structure (from _output_formats), whose columns' `value` fields will be filled.
2492
+
2493
+ Returns
2494
+ -------
2495
+ dict
2496
+ The same columns_struct with values populated. Non-empty values are not overwritten.
2497
+ """
2498
+ # Common population first
2499
+ col_data = populate_common_columns(element, columns_struct)
2500
+ # Overlay glossary-specific extras: categories lists
2501
+ header_props = _extract_referenceable_properties(element)
2502
+ guid = header_props.get('GUID')
2503
+ extra: dict = {}
2504
+ if guid:
2505
+ try:
2506
+ categories = self.get_categories_for_glossary(guid)
2507
+ except Exception:
2508
+ categories = None
2509
+ if isinstance(categories, list):
2510
+ cat_display_list = []
2511
+ cat_qn_list = []
2512
+ for category in categories:
2513
+ gcp = category.get('glossaryCategoryProperties', {})
2514
+ dn = (gcp.get('displayName') or '')
2515
+ qn = (gcp.get('qualifiedName') or '')
2516
+ if dn:
2517
+ cat_display_list.append(dn)
2518
+ if qn:
2519
+ cat_qn_list.append(qn)
2520
+ if cat_display_list:
2521
+ extra['categories_names'] = ", \n".join(cat_display_list)
2522
+ if cat_qn_list:
2523
+ extra['categories_qualified_names'] = ", \n".join(cat_qn_list)
2524
+ return overlay_additional_values(col_data, extra)
2525
+
2526
+ def _extract_term_properties(self, element: dict, columns_struct: dict) -> dict:
2527
+ """Extract glossary term columns for rendering.
2528
+
2529
+ Populates standard columns via `populate_common_columns`, and if requested by the
2530
+ selected columns, derives a classifications string (from `elementHeader.collectionCategories`)
2531
+ into the `classifications` column.
2532
+
2533
+ Parameters
2534
+ ----------
2535
+ element : dict
2536
+ Raw term element returned by the OMVS.
2537
+ columns_struct : dict
2538
+ The chosen format-set structure whose column `value`s will be set.
2539
+
2540
+ Returns
2541
+ -------
2542
+ dict
2543
+ The same `columns_struct` with values populated.
2544
+ """
2545
+ # Use centralized population
2546
+ col_data = populate_common_columns(element, columns_struct)
2547
+ # Term-specific classifications (collectionCategories) to 'classifications' column
2548
+ columns_list = col_data.get('formats', {}).get('attributes', [])
2549
+ try:
2550
+ classification_names = ""
2551
+ classifications = element.get('elementHeader', {}).get("collectionCategories", [])
2552
+ for classification in classifications:
2553
+ nm = classification.get('classificationName')
2554
+ if nm:
2555
+ classification_names += f"{nm}, "
2556
+ if classification_names:
2557
+ for column in columns_list:
2558
+ if column.get('key') == 'classifications' and column.get('value') in (None, ""):
2559
+ column['value'] = classification_names[:-2]
2560
+ break
2561
+ except Exception:
2562
+ pass
2563
+ return col_data
2564
+
2565
+ def _get_term_additional_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
2566
+ additional: dict = {}
2567
+ try:
2568
+ classifications = element.get('elementHeader', {}).get('otherClassifications', [])
2569
+ glossary_name = ''
2570
+ if classifications:
2571
+ cls_props = classifications[0].get('classificationProperties', {}) or {}
2572
+ g_guid = cls_props.get('anchorScopeGUID')
2573
+ if g_guid and hasattr(self, 'get_glossary_by_guid'):
2574
+ try:
2575
+ gl = self.get_glossary_by_guid(g_guid)
2576
+ if isinstance(gl, dict):
2577
+ if output_format == 'REPORT':
2578
+ glossary_name = gl.get('glossaryProperties', {}).get('displayName', '')
2579
+ else:
2580
+ glossary_name = gl.get('glossaryProperties', {}).get('qualifiedName', '')
2581
+ except Exception:
2582
+ pass
2583
+ if glossary_name:
2584
+ additional['in_glossary'] = glossary_name
2585
+ except Exception:
2586
+ pass
2587
+ try:
2588
+ if hasattr(self, 'get_categories_for_term') and term_guid:
2589
+ cats = self.get_categories_for_term(term_guid)
2590
+ names = []
2591
+ if isinstance(cats, list):
2592
+ for c in cats:
2593
+ gcp = c.get('glossaryCategoryProperties', {})
2594
+ val = gcp.get('displayName') if output_format in ['REPORT', 'LIST'] else gcp.get('qualifiedName')
2595
+ if val:
2596
+ names.append(val)
2597
+ if names:
2598
+ additional['categories'] = ", \n".join(names)
2599
+ except Exception:
2600
+ pass
2601
+ return additional
2602
+
2603
+ def _generate_glossary_output(self, elements: dict | list[dict], search_string: str,
2604
+ element_type_name: str | None,
2605
+ output_format: str = 'DICT',
2606
+ report_spec: dict | str = None) -> str | list[dict]:
2607
+ entity_type = 'Glossary'
2608
+ output_formats = resolve_output_formats(entity_type, output_format, report_spec)
2609
+ return generate_output(
2610
+ elements=elements,
2611
+ search_string=search_string,
2612
+ entity_type=entity_type,
2613
+ output_format=output_format,
2614
+ extract_properties_func=self._extract_glossary_properties,
2615
+ get_additional_props_func=None,
2616
+ columns_struct=output_formats,
2617
+ )
2618
+
2619
+ def _generate_term_output(self, elements: dict | list[dict], search_string: str,
2620
+ element_type_name: str | None,
2621
+ output_format: str = 'DICT',
2622
+ report_spec: dict | str = None) -> str | list[dict]:
2623
+ entity_type = 'GlossaryTerm'
2624
+ output_formats = resolve_output_formats(entity_type, output_format, report_spec)
2625
+ return generate_output(
2626
+ elements=elements,
2627
+ search_string=search_string,
2628
+ entity_type=entity_type,
2629
+ output_format=output_format,
2630
+ extract_properties_func=self._extract_term_properties,
2631
+ get_additional_props_func=self._get_term_additional_properties,
2632
+ columns_struct=output_formats,
2633
+ )
2634
+
2635
+ async def _async_get_glossary_term_statuses(self) -> [str]:
2636
+ url = (f"{self.platform_url}/servers/{self.view_server}"
2637
+ f"/api/open-metadata/glossary-manager/glossaries/terms/status-list")
2638
+ response = await self._async_make_request("GET", url)
2639
+ return response.json().get("statuses", [])
2640
+
2641
+ def get_glossary_term_statuses(self) -> [str]:
2642
+ loop = asyncio.get_event_loop()
2643
+ response = loop.run_until_complete(self._async_get_glossary_term_statuses())
2644
+ return response
2645
+
2646
+ async def _async_get_glossary_term_rel_statuses(self) -> [str]:
2647
+ url = (f"{self.platform_url}/servers/{self.view_server}"
2648
+ f"/api/open-metadata/glossary-manager/glossaries/terms/relationships/status-list")
2649
+ response = await self._async_make_request("GET", url)
2650
+ return response.json().get("statuses", [])
2651
+
2652
+ def get_glossary_term_rel_statuses(self) -> [str]:
2653
+ loop = asyncio.get_event_loop()
2654
+ response = loop.run_until_complete(self._async_get_glossary_term_rel_statuses())
2655
+ return response
2656
+
2657
+ async def _async_get_glossary_term_activity_types(self) -> [str]:
2658
+ url = (f"{self.platform_url}/servers/{self.view_server}"
2659
+ f"/api/open-metadata/glossary-manager/glossaries/terms/activity-types")
2660
+ response = await self._async_make_request("GET", url)
2661
+ return response.json().get("types", [])
2662
+
2663
+ def get_glossary_term_activity_types(self) -> [str]:
2664
+ loop = asyncio.get_event_loop()
2665
+ response = loop.run_until_complete(self._async_get_glossary_term_statuses())
2666
+ return response
2667
+
2668
+ async def _async_get_term_relationship_types(self) -> [str]:
2669
+ url = (f"{self.platform_url}/servers/{self.view_server}"
2670
+ f"/api/open-metadata/glossary-manager/glossaries/terms/relationships/type-names")
2671
+ response = await self._async_make_request("GET", url)
2672
+ return response.json().get("names", [])
2673
+
2674
+ def get_term_relationship_types(self) -> [str]:
2675
+ loop = asyncio.get_event_loop()
2676
+ response = loop.run_until_complete(self._async_get_term_relationship_types())
2677
+ return response
2678
+
2679
+ @dynamic_catch
2680
+ async def _async_find_glossaries(self, search_string: str = "*",
2681
+ starts_with: bool = True, ends_with: bool = False,
2682
+ ignore_case: bool = False,
2683
+ anchor_domain: Optional[str] = None,
2684
+ metadata_element_type: str = "Glossary",
2685
+ metadata_element_subtypes: Optional[list[str]] = None,
2686
+ skip_relationships: Optional[list[str]] = None,
2687
+ include_only_relationships: Optional[list[str]] = None,
2688
+ skip_classified_elements: Optional[list[str]] = None,
2689
+ include_only_classified_elements: Optional[list[str]] = None,
2690
+ graph_query_depth: int = 3,
2691
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
2692
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
2693
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
2694
+ sequencing_property: Optional[str] = None,
2695
+ output_format: str = "JSON",
2696
+ report_spec: str | dict = None,
2697
+ start_from: int = 0, page_size: int = 100,
2698
+ property_names: Optional[list[str]] = None,
2699
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
2700
+ """ Retrieve the list of glossary metadata elements that contain the search string. Async Version.
2701
+
2702
+ Parameters
2703
+ ----------
2704
+ search_string: str
2705
+ Search string to match against - None or '*' indicate match against all glossaries.
2706
+ starts_with : bool, [default=True], optional
2707
+ Starts with the supplied string.
2708
+ ends_with : bool, [default=False], optional
2709
+ Ends with the supplied string
2710
+ ignore_case : bool, [default=False], optional
2711
+ Ignore case when searching
2712
+ anchor_domain: str, optional
2713
+ The anchor domain to search in.
2714
+ metadata_element_type: str, optional, [default="Glossary"]
2715
+ The type of metadata element to search for.
2716
+ metadata_element_subtypes: list[str], optional
2717
+ The subtypes of metadata element to search for.
2718
+ skip_relationships: list[str], optional
2719
+ The types of relationships to skip.
2720
+ include_only_relationships: list[str], optional
2721
+ The types of relationships to include.
2722
+ skip_classified_elements: list[str], optional
2723
+ The types of classified elements to skip.
2724
+ include_only_classified_elements: list[str], optional
2725
+ The types of classified elements to include.
2726
+ graph_query_depth: int, [default=3], optional
2727
+ The depth of the graph query.
2728
+ governance_zone_filter: list[str], optional
2729
+ The governance zones to search in.
2730
+ as_of_time: str, optional
2731
+ The time to search as of.
2732
+ effective_time: str, optional
2733
+ The effective time to search at.
2734
+ relationship_page_size: int, [default=0], optional
2735
+ The page size for relationships.
2736
+ limit_results_by_status: list[str], optional
2737
+ The statuses to limit results by.
2738
+ sequencing_order: str, optional
2739
+ The order to sequence results by.
2740
+ sequencing_property: str, optional
2741
+ The property to sequence results by.
2742
+ output_format: str, default = "JSON"
2743
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
2744
+ report_spec: str | dict , optional, default = None
2745
+ - The desired output columns/fields to include.
2746
+ start_from: int, [default=0], optional
2747
+ When multiple pages of results are available, the page number to start from.
2748
+ page_size: int, [default=100]
2749
+ The number of items to return in a single page.
2750
+ property_names: list[str], optional
2751
+ The names of properties to search for.
2752
+ body: dict | SearchStringRequestBody, optional, default = None
2753
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
2754
+
2755
+ Returns
2756
+ -------
2757
+ List | str
2758
+
2759
+ Output depends on the output format specified.
2760
+
2761
+ Raises
2762
+ ------
2763
+
2764
+ ValidationError
2765
+ If the client passes incorrect parameters on the request that don't conform to the data model.
2766
+ PyegeriaException
2767
+ Issues raised in communicating or server side processing.
2768
+ NotAuthorizedException
2769
+ The principle specified by the user_id does not have authorization for the requested action
2770
+
2771
+ """
2772
+ response = await self._async_find_collections(search_string=search_string, starts_with=starts_with,
2773
+ ends_with=ends_with, ignore_case=ignore_case,
2774
+ anchor_domain=anchor_domain,
2775
+ metadata_element_type=metadata_element_type,
2776
+ metadata_element_subtypes=metadata_element_subtypes,
2777
+ skip_relationships=skip_relationships,
2778
+ include_only_relationships=include_only_relationships,
2779
+ skip_classified_elements=skip_classified_elements,
2780
+ include_only_classified_elements=include_only_classified_elements,
2781
+ graph_query_depth=graph_query_depth,
2782
+ governance_zone_filter=governance_zone_filter,
2783
+ as_of_time=as_of_time, effective_time=effective_time,
2784
+ relationship_page_size=relationship_page_size,
2785
+ limit_results_by_status=limit_results_by_status,
2786
+ sequencing_order=sequencing_order,
2787
+ sequencing_property=sequencing_property,
2788
+ output_format=output_format, report_spec=report_spec,
2789
+ start_from=start_from, page_size=page_size,
2790
+ property_names=property_names, body=body)
2791
+ return response
2792
+
2793
+ @dynamic_catch
2794
+ def find_glossaries(self, search_string: str = "*",
2795
+ starts_with: bool = True, ends_with: bool = False,
2796
+ ignore_case: bool = False,
2797
+ anchor_domain: Optional[str] = None,
2798
+ metadata_element_type: str = "Glossary",
2799
+ metadata_element_subtypes: Optional[list[str]] = None,
2800
+ skip_relationships: Optional[list[str]] = None,
2801
+ include_only_relationships: Optional[list[str]] = None,
2802
+ skip_classified_elements: Optional[list[str]] = None,
2803
+ include_only_classified_elements: Optional[list[str]] = None,
2804
+ graph_query_depth: int = 3,
2805
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
2806
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
2807
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
2808
+ sequencing_property: Optional[str] = None,
2809
+ output_format: str = "JSON",
2810
+ report_spec: str | dict = None,
2811
+ start_from: int = 0, page_size: int = 100,
2812
+ property_names: Optional[list[str]] = None,
2813
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
2814
+ """ Retrieve the list of glossary metadata elements that contain the search string.
2815
+
2816
+ Parameters
2817
+ ----------
2818
+ search_string: str
2819
+ Search string to match against - None or '*' indicate match against all glossaries.
2820
+ starts_with : bool, [default=True], optional
2821
+ Starts with the supplied string.
2822
+ ends_with : bool, [default=False], optional
2823
+ Ends with the supplied string
2824
+ ignore_case : bool, [default=False], optional
2825
+ Ignore case when searching
2826
+ anchor_domain: str, optional
2827
+ The anchor domain to search in.
2828
+ metadata_element_type: str, optional, [default="Glossary"]
2829
+ The type of metadata element to search for.
2830
+ metadata_element_subtypes: list[str], optional
2831
+ The subtypes of metadata element to search for.
2832
+ skip_relationships: list[str], optional
2833
+ The types of relationships to skip.
2834
+ include_only_relationships: list[str], optional
2835
+ The types of relationships to include.
2836
+ skip_classified_elements: list[str], optional
2837
+ The types of classified elements to skip.
2838
+ include_only_classified_elements: list[str], optional
2839
+ The types of classified elements to include.
2840
+ graph_query_depth: int, [default=3], optional
2841
+ The depth of the graph query.
2842
+ governance_zone_filter: list[str], optional
2843
+ The governance zones to search in.
2844
+ as_of_time: str, optional
2845
+ The time to search as of.
2846
+ effective_time: str, optional
2847
+ The effective time to search at.
2848
+ relationship_page_size: int, [default=0], optional
2849
+ The page size for relationships.
2850
+ limit_results_by_status: list[str], optional
2851
+ The statuses to limit results by.
2852
+ sequencing_order: str, optional
2853
+ The order to sequence results by.
2854
+ sequencing_property: str, optional
2855
+ The property to sequence results by.
2856
+ output_format: str, default = "JSON"
2857
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
2858
+ report_spec: str | dict , optional, default = None
2859
+ - The desired output columns/fields to include.
2860
+ start_from: int, [default=0], optional
2861
+ When multiple pages of results are available, the page number to start from.
2862
+ page_size: int, [default=100]
2863
+ The number of items to return in a single page.
2864
+ property_names: list[str], optional
2865
+ The names of properties to search for.
2866
+ body: dict | SearchStringRequestBody, optional, default = None
2867
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
2868
+
2869
+ Returns
2870
+ -------
2871
+ List | str
2872
+
2873
+ Output depends on the output format specified.
2874
+
2875
+ Raises
2876
+ -------
2877
+
2878
+ ValidationError
2879
+ If the client passes incorrect parameters on the request that don't conform to the data model.
2880
+ PyegeriaException
2881
+ Issues raised in communicating or server side processing.
2882
+ NotAuthorizedException
2883
+ The principle specified by the user_id does not have authorization for the requested action
2884
+
2885
+ """
2886
+ loop = asyncio.get_event_loop()
2887
+ return loop.run_until_complete(self._async_find_glossaries(search_string=search_string,
2888
+ starts_with=starts_with,
2889
+ ends_with=ends_with,
2890
+ ignore_case=ignore_case,
2891
+ anchor_domain=anchor_domain,
2892
+ metadata_element_type=metadata_element_type,
2893
+ metadata_element_subtypes=metadata_element_subtypes,
2894
+ skip_relationships=skip_relationships,
2895
+ include_only_relationships=include_only_relationships,
2896
+ skip_classified_elements=skip_classified_elements,
2897
+ include_only_classified_elements=include_only_classified_elements,
2898
+ graph_query_depth=graph_query_depth,
2899
+ governance_zone_filter=governance_zone_filter,
2900
+ as_of_time=as_of_time,
2901
+ effective_time=effective_time,
2902
+ relationship_page_size=relationship_page_size,
2903
+ limit_results_by_status=limit_results_by_status,
2904
+ sequencing_order=sequencing_order,
2905
+ sequencing_property=sequencing_property,
2906
+ output_format=output_format,
2907
+ report_spec=report_spec,
2908
+ start_from=start_from,
2909
+ page_size=page_size,
2910
+ property_names=property_names,
2911
+ body=body))
2912
+
2913
+ async def _async_get_glossaries_by_name(self, filter_string: Optional[str] = None, classification_names: Optional[list[str]] = None,
2914
+ body: Optional[dict | FilterRequestBody] = None,
2915
+ start_from: int = 0, page_size: int = 0,
2916
+ output_format: str = 'JSON',
2917
+ report_spec: str | dict = None) -> dict | str:
2918
+ return await self._async_get_collections_by_name(filter_string, classification_names, body, start_from, page_size, output_format, report_spec)
2919
+
2920
+
2921
+ def get_glossaries_by_name(self, filter_string: Optional[str] = None, classification_names: Optional[list[str]] = None,
2922
+ body: Optional[dict | FilterRequestBody] = None,
2923
+ start_from: int = 0, page_size: int = 0,
2924
+ output_format: str = 'JSON',
2925
+ report_spec: str | dict = None) -> dict | str:
2926
+ loop = asyncio.get_event_loop()
2927
+ response = loop.run_until_complete(
2928
+ self._async_get_glossaries_by_name(filter_string, classification_names, body,start_from, page_size,
2929
+ output_format, report_spec))
2930
+ return response
2931
+
2932
+ async def _async_get_glossary_by_guid(self, glossary_guid: str, element_type: str = "Glossary", body: Optional[dict | GetRequestBody] = None,
2933
+ output_format: str = "JSON", report_spec: str | dict = None) -> dict | str:
2934
+
2935
+ return await self._async_get_collection_by_guid(glossary_guid, element_type, body, output_format, report_spec)
2936
+
2937
+
2938
+
2939
+ def get_glossary_by_guid(self, glossary_guid: str, element_type: str = "Glossary", body: dict| GetRequestBody=None,
2940
+ output_format: str = "JSON", report_spec: str | dict = None) -> dict | str:
2941
+ loop = asyncio.get_event_loop()
2942
+ response = loop.run_until_complete(
2943
+ self._async_get_glossary_by_guid(glossary_guid, element_type, body,output_format, report_spec))
2944
+ return response
2945
+
2946
+
2947
+
2948
+ async def _async_get_terms_by_name(self, filter_string: Optional[str] = None, classification_names: Optional[list[str]] = None,
2949
+ body: Optional[dict | FilterRequestBody] = None,
2950
+ start_from: int = 0, page_size: int = 0,
2951
+ output_format: str = 'JSON',
2952
+ report_spec: str | dict = None) -> list:
2953
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
2954
+ f"terms/by-name")
2955
+ response = await self._async_get_name_request(url, _type="GlossaryTerm",
2956
+ _gen_output=self._generate_term_output,
2957
+ filter_string=filter_string,
2958
+ classification_names=classification_names,
2959
+ start_from=start_from, page_size=page_size,
2960
+ output_format=output_format, report_spec=report_spec,
2961
+ body=body)
2962
+ return response
2963
+
2964
+ def get_terms_by_name(self, filter_string: Optional[str] = None, classification_names: Optional[list[str]] = None,
2965
+ body: Optional[dict | FilterRequestBody] = None,
2966
+ start_from: int = 0, page_size: int = 0,
2967
+ output_format: str = 'JSON',
2968
+ report_spec: str | dict = None) -> list:
2969
+ loop = asyncio.get_event_loop()
2970
+ response = loop.run_until_complete(
2971
+ self._async_get_terms_by_name(filter_string, classification_names, body,start_from, page_size,
2972
+ output_format, report_spec))
2973
+ return response
2974
+
2975
+ async def _async_get_term_by_guid(self, term_guid: str, element_type: str = "GlossaryTerm", body: dict| GetRequestBody=None,
2976
+ output_format: str = "JSON", report_spec: str | dict = None) -> dict | str:
2977
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms/"
2978
+ f"{term_guid}")
2979
+ response = await self._async_get_guid_request(url, _type=element_type,
2980
+ _gen_output=self._generate_term_output,
2981
+ output_format=output_format, report_spec=report_spec,
2982
+ body=body)
2983
+ return response
2984
+
2985
+ def get_term_by_guid(self, term_guid: str, element_type: str = "GlossaryTerm", body: dict| GetRequestBody=None,
2986
+ output_format: str = "JSON", report_spec: str | dict = None) -> dict | str:
2987
+ loop = asyncio.get_event_loop()
2988
+ response = loop.run_until_complete(self._async_get_term_by_guid(term_guid, element_type, body, output_format, report_spec))
2989
+ return response
2990
+
2991
+ @dynamic_catch
2992
+ async def _async_find_glossary_terms(self, search_string: str = "*",
2993
+ starts_with: bool = True, ends_with: bool = False,
2994
+ ignore_case: bool = False,
2995
+ anchor_domain: Optional[str] = None,
2996
+ metadata_element_type: str = "GlossaryTerm",
2997
+ metadata_element_subtypes: Optional[list[str]] = None,
2998
+ skip_relationships: Optional[list[str]] = None,
2999
+ include_only_relationships: Optional[list[str]] = None,
3000
+ skip_classified_elements: Optional[list[str]] = None,
3001
+ include_only_classified_elements: Optional[list[str]] = None,
3002
+ graph_query_depth: int = 3,
3003
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
3004
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
3005
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
3006
+ sequencing_property: Optional[str] = None,
3007
+ output_format: str = "JSON",
3008
+ report_spec: str | dict = "Glossary-Term-DrE",
3009
+ start_from: int = 0, page_size: int = 100,
3010
+ property_names: Optional[list[str]] = None,
3011
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
3012
+ """ Retrieve the list of glossary term metadata elements that contain the search string. Async Version.
3013
+
3014
+ Parameters
3015
+ ----------
3016
+ search_string: str
3017
+ Search string to match against - None or '*' indicate match against all glossary terms.
3018
+ starts_with : bool, [default=True], optional
3019
+ Starts with the supplied string.
3020
+ ends_with : bool, [default=False], optional
3021
+ Ends with the supplied string
3022
+ ignore_case : bool, [default=False], optional
3023
+ Ignore case when searching
3024
+ anchor_domain: str, optional
3025
+ The anchor domain to search in.
3026
+ metadata_element_type: str, optional, [default="GlossaryTerm"]
3027
+ The type of metadata element to search for.
3028
+ metadata_element_subtypes: list[str], optional
3029
+ The subtypes of metadata element to search for.
3030
+ skip_relationships: list[str], optional
3031
+ The types of relationships to skip.
3032
+ include_only_relationships: list[str], optional
3033
+ The types of relationships to include.
3034
+ skip_classified_elements: list[str], optional
3035
+ The types of classified elements to skip.
3036
+ include_only_classified_elements: list[str], optional
3037
+ The types of classified elements to include.
3038
+ graph_query_depth: int, [default=3], optional
3039
+ The depth of the graph query.
3040
+ governance_zone_filter: list[str], optional
3041
+ The governance zones to search in.
3042
+ as_of_time: str, optional
3043
+ The time to search as of.
3044
+ effective_time: str, optional
3045
+ The effective time to search at.
3046
+ relationship_page_size: int, [default=0], optional
3047
+ The page size for relationships.
3048
+ limit_results_by_status: list[str], optional
3049
+ The statuses to limit results by.
3050
+ sequencing_order: str, optional
3051
+ The order to sequence results by.
3052
+ sequencing_property: str, optional
3053
+ The property to sequence results by.
3054
+ output_format: str, default = "JSON"
3055
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
3056
+ report_spec: str | dict , optional, default = "Glossary-Term-DrE"
3057
+ - The desired output columns/fields to include.
3058
+ start_from: int, [default=0], optional
3059
+ When multiple pages of results are available, the page number to start from.
3060
+ page_size: int, [default=100]
3061
+ The number of items to return in a single page.
3062
+ property_names: list[str], optional
3063
+ The names of properties to search for.
3064
+ body: dict | SearchStringRequestBody, optional, default = None
3065
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
3066
+
3067
+ Returns
3068
+ -------
3069
+ List | str
3070
+
3071
+ Output depends on the output format specified.
3072
+
3073
+ Raises
3074
+ ------
3075
+
3076
+ ValidationError
3077
+ If the client passes incorrect parameters on the request that don't conform to the data model.
3078
+ PyegeriaException
3079
+ Issues raised in communicating or server side processing.
3080
+ NotAuthorizedException
3081
+ The principle specified by the user_id does not have authorization for the requested action
3082
+
3083
+ """
3084
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms/"
3085
+ f"by-search-string")
3086
+ response = await self._async_find_request(url, _type=metadata_element_type, _gen_output=self._generate_term_output,
3087
+ search_string=search_string, starts_with=starts_with,
3088
+ ends_with=ends_with, ignore_case=ignore_case,
3089
+ anchor_domain=anchor_domain,
3090
+ metadata_element_type=metadata_element_type,
3091
+ metadata_element_subtypes=metadata_element_subtypes,
3092
+ skip_relationships=skip_relationships,
3093
+ include_only_relationships=include_only_relationships,
3094
+ skip_classified_elements=skip_classified_elements,
3095
+ include_only_classified_elements=include_only_classified_elements,
3096
+ graph_query_depth=graph_query_depth,
3097
+ governance_zone_filter=governance_zone_filter,
3098
+ as_of_time=as_of_time, effective_time=effective_time,
3099
+ relationship_page_size=relationship_page_size,
3100
+ limit_results_by_status=limit_results_by_status,
3101
+ sequencing_order=sequencing_order,
3102
+ sequencing_property=sequencing_property,
3103
+ output_format=output_format, report_spec=report_spec,
3104
+ start_from=start_from, page_size=page_size,
3105
+ property_names=property_names, body=body)
3106
+
3107
+ return response
3108
+
3109
+ @dynamic_catch
3110
+ def find_glossary_terms(self, search_string: str = "*",
3111
+ starts_with: bool = True, ends_with: bool = False,
3112
+ ignore_case: bool = False,
3113
+ anchor_domain: Optional[str] = None,
3114
+ metadata_element_type: str = "GlossaryTerm",
3115
+ metadata_element_subtypes: Optional[list[str]] = None,
3116
+ skip_relationships: Optional[list[str]] = None,
3117
+ include_only_relationships: Optional[list[str]] = None,
3118
+ skip_classified_elements: Optional[list[str]] = None,
3119
+ include_only_classified_elements: Optional[list[str]] = None,
3120
+ graph_query_depth: int = 3,
3121
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
3122
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
3123
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
3124
+ sequencing_property: Optional[str] = None,
3125
+ output_format: str = "JSON",
3126
+ report_spec: str | dict = "Glossary-Term-DrE",
3127
+ start_from: int = 0, page_size: int = 100,
3128
+ property_names: Optional[list[str]] = None,
3129
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
3130
+ """ Retrieve the list of glossary term metadata elements that contain the search string.
3131
+
3132
+ Parameters
3133
+ ----------
3134
+ search_string: str
3135
+ Search string to match against - None or '*' indicate match against all glossary terms.
3136
+ starts_with : bool, [default=True], optional
3137
+ Starts with the supplied string.
3138
+ ends_with : bool, [default=False], optional
3139
+ Ends with the supplied string
3140
+ ignore_case : bool, [default=False], optional
3141
+ Ignore case when searching
3142
+ anchor_domain: str, optional
3143
+ The anchor domain to search in.
3144
+ metadata_element_type: str, optional, [default="GlossaryTerm"]
3145
+ The type of metadata element to search for.
3146
+ metadata_element_subtypes: list[str], optional
3147
+ The subtypes of metadata element to search for.
3148
+ skip_relationships: list[str], optional
3149
+ The types of relationships to skip.
3150
+ include_only_relationships: list[str], optional
3151
+ The types of relationships to include.
3152
+ skip_classified_elements: list[str], optional
3153
+ The types of classified elements to skip.
3154
+ include_only_classified_elements: list[str], optional
3155
+ The types of classified elements to include.
3156
+ graph_query_depth: int, [default=3], optional
3157
+ The depth of the graph query.
3158
+ governance_zone_filter: list[str], optional
3159
+ The governance zones to search in.
3160
+ as_of_time: str, optional
3161
+ The time to search as of.
3162
+ effective_time: str, optional
3163
+ The effective time to search at.
3164
+ relationship_page_size: int, [default=0], optional
3165
+ The page size for relationships.
3166
+ limit_results_by_status: list[str], optional
3167
+ The statuses to limit results by.
3168
+ sequencing_order: str, optional
3169
+ The order to sequence results by.
3170
+ sequencing_property: str, optional
3171
+ The property to sequence results by.
3172
+ output_format: str, default = "JSON"
3173
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
3174
+ report_spec: str | dict , optional, default = "Glossary-Term-DrE"
3175
+ - The desired output columns/fields to include.
3176
+ start_from: int, [default=0], optional
3177
+ When multiple pages of results are available, the page number to start from.
3178
+ page_size: int, [default=100]
3179
+ The number of items to return in a single page.
3180
+ property_names: list[str], optional
3181
+ The names of properties to search for.
3182
+ body: dict | SearchStringRequestBody, optional, default = None
3183
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
3184
+
3185
+ Returns
3186
+ -------
3187
+ List | str
3188
+
3189
+ Output depends on the output format specified.
3190
+
3191
+ Raises
3192
+ -------
3193
+
3194
+ ValidationError
3195
+ If the client passes incorrect parameters on the request that don't conform to the data model.
3196
+ PyegeriaException
3197
+ Issues raised in communicating or server side processing.
3198
+ NotAuthorizedException
3199
+ The principle specified by the user_id does not have authorization for the requested action
3200
+
3201
+ """
3202
+ loop = asyncio.get_event_loop()
3203
+ return loop.run_until_complete(self._async_find_glossary_terms(search_string=search_string,
3204
+ starts_with=starts_with,
3205
+ ends_with=ends_with,
3206
+ ignore_case=ignore_case,
3207
+ anchor_domain=anchor_domain,
3208
+ metadata_element_type=metadata_element_type,
3209
+ metadata_element_subtypes=metadata_element_subtypes,
3210
+ skip_relationships=skip_relationships,
3211
+ include_only_relationships=include_only_relationships,
3212
+ skip_classified_elements=skip_classified_elements,
3213
+ include_only_classified_elements=include_only_classified_elements,
3214
+ graph_query_depth=graph_query_depth,
3215
+ governance_zone_filter=governance_zone_filter,
3216
+ as_of_time=as_of_time,
3217
+ effective_time=effective_time,
3218
+ relationship_page_size=relationship_page_size,
3219
+ limit_results_by_status=limit_results_by_status,
3220
+ sequencing_order=sequencing_order,
3221
+ sequencing_property=sequencing_property,
3222
+ output_format=output_format,
3223
+ report_spec=report_spec,
3224
+ start_from=start_from,
3225
+ page_size=page_size,
3226
+ property_names=property_names,
3227
+ body=body))
3228
+
3229
+
3230
+ if __name__ == "__main__":
3231
+ print("Main-Glossary Manager")