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,573 @@
1
+ """
2
+ SPDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ This is a simple class to create and manage a connection to an Egeria backend. It is the Superclass for the
6
+ different client capabilities. It also provides the common methods used to make restful self.session to Egeria.
7
+
8
+ """
9
+
10
+ import asyncio
11
+ import inspect
12
+ import json
13
+ import os
14
+
15
+ import httpcore
16
+ import httpx
17
+ from httpx import AsyncClient, Response, HTTPStatusError
18
+ from loguru import logger
19
+
20
+ from pyegeria.core._exceptions import (
21
+ PyegeriaAPIException, PyegeriaConnectionException, PyegeriaInvalidParameterException,
22
+ PyegeriaUnknownException, PyegeriaClientException
23
+ )
24
+ from pyegeria.core._globals import enable_ssl_check, max_paging_size
25
+ from pyegeria.core._validators import (
26
+ validate_name,
27
+ validate_server_name,
28
+ validate_url,
29
+ validate_user_id,
30
+ )
31
+
32
+ ...
33
+
34
+
35
+ class BaseServerClient:
36
+ """
37
+ An abstract class used to establish connectivity for an Egeria Client
38
+ for a particular server, platform and user. This is a base client that more functional clients inherit from.
39
+
40
+ Attributes
41
+ ----------
42
+ server_name : str
43
+ Name of the OMAG server to use
44
+ platform_url : str
45
+ URL of the server platform to connect to
46
+ user_id : str
47
+ The identity of the user calling the method - this sets a default optionally used by the methods
48
+ when the user doesn't pass the user_id on a method call.
49
+ user_pwd : str
50
+ The password used to authenticate the server identity
51
+ page_size : int
52
+ The default page size for paged requests.
53
+ token : str
54
+ An optional bearer token for authentication.
55
+ token_src : str
56
+ The source of the bearer token (e.g., 'Egeria').
57
+ api_key : str
58
+ An optional API key for authentication.
59
+
60
+ """
61
+
62
+ json_header = {"Content-Type": "application/json"}
63
+
64
+ def __init__(
65
+ self,
66
+ server_name: str,
67
+ platform_url: str,
68
+ user_id: str = None,
69
+ user_pwd: str = None,
70
+ token: str = None,
71
+ token_src: str = None,
72
+ api_key: str = None,
73
+ page_size: int = max_paging_size,
74
+ ):
75
+ self.server_name = validate_server_name(server_name)
76
+ self.platform_url = validate_url(platform_url)
77
+ self.user_id = user_id
78
+ self.user_pwd = user_pwd
79
+ self.page_size = page_size
80
+ self.token_src = token_src
81
+ self.token = token
82
+ self.exc_type = None
83
+ self.exc_value = None
84
+ self.exc_tb = None
85
+
86
+ #
87
+ # I'm commenting this out since you should only have to use tokens if you want - just have to
88
+ # create or set the token with the appropriate methods as desired.
89
+ # if token is None:
90
+ # token = os.environ.get("Egeria_Bearer_Token", None)
91
+ # if token is None: # No token found - so make one
92
+ # self.create_egeria_bearer_token(self.user_id, self.user_pwd)
93
+ # else:
94
+ # self.token = token
95
+
96
+ if api_key is None:
97
+ api_key = os.environ.get("API_KEY", None)
98
+ self.api_key = api_key
99
+
100
+ self.headers = {
101
+ "Content-Type": "application/json",
102
+ }
103
+ self.text_headers = {
104
+ "Content-Type": "text/plain",
105
+ }
106
+ if self.api_key is not None:
107
+ self.headers["X-Api-Key"] = self.api_key
108
+ self.text_headers["X-Api-Key"] = self.api_key
109
+
110
+ if token is not None:
111
+ self.headers["Authorization"] = f"Bearer {token}"
112
+ self.text_headers["Authorization"] = f"Bearer {token}"
113
+
114
+ v_url = validate_url(platform_url)
115
+
116
+ if v_url:
117
+ self.platform_url = platform_url
118
+ if validate_server_name(server_name):
119
+ self.server_name = server_name
120
+ self.session = AsyncClient(verify=enable_ssl_check)
121
+ self.command_root: str = f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/"
122
+
123
+ try:
124
+ result = self.check_connection()
125
+ logger.debug(f"client initialized, platform origin is: {result}")
126
+ except PyegeriaConnectionException as e:
127
+ raise
128
+
129
+ async def _async_check_connection(self) -> str:
130
+ """Check if the connection is working. Async version.
131
+
132
+ Returns
133
+ -------
134
+ str
135
+ The platform origin string if reachable, otherwise an empty string.
136
+
137
+ Raises
138
+ ------
139
+ PyegeriaConnectionException
140
+ If the connection to the platform fails.
141
+ """
142
+ try:
143
+ response = await self.async_get_platform_origin()
144
+ return response
145
+
146
+ except PyegeriaConnectionException as e:
147
+ raise
148
+ def check_connection(self) -> str:
149
+ """Check if the connection is working.
150
+
151
+ Returns
152
+ -------
153
+ str
154
+ The platform origin string if reachable, otherwise an empty string.
155
+
156
+ Raises
157
+ ------
158
+ PyegeriaConnectionException
159
+ If the connection to the platform fails.
160
+ """
161
+ loop = asyncio.get_event_loop()
162
+ response = loop.run_until_complete(self._async_check_connection())
163
+ return response
164
+
165
+ def __enter__(self):
166
+ return self
167
+
168
+ def __exit__(self, exc_type, exc_val, exc_tb):
169
+ self.session.aclose()
170
+ if exc_type is not None:
171
+ self.exc_type = exc_type
172
+ self.exc_val = exc_val
173
+ self.exc_tb = exc_tb
174
+
175
+ return False # allows exceptions to propagate
176
+
177
+ def __str__(self):
178
+ return (f"EgeriaClient(server_name={self.server_name}, platform_url={self.platform_url}, "
179
+ f"user_id={self.user_id}, page_size={self.page_size})")
180
+
181
+ async def _async_close_session(self) -> None:
182
+ """Close the session"""
183
+ await self.session.aclose()
184
+
185
+ def close_session(self) -> None:
186
+ """Close the session"""
187
+ loop = asyncio.get_event_loop()
188
+ loop.run_until_complete(self._async_close_session())
189
+ return
190
+
191
+ async def _async_create_egeria_bearer_token(
192
+ self, user_id: str , password: str
193
+ ) -> str:
194
+ """Create and set an Egeria Server Bearer Token for the user. Async version
195
+ Parameters
196
+ ----------
197
+ user_id : str, opt
198
+ The user id to authenticate with. If None, then user_id from class instance used.
199
+ password : str, opt
200
+ The password for the user. If None, then user_pwd from class instance is used.
201
+
202
+ Returns
203
+ -------
204
+ token
205
+ The bearer token for the specified user.
206
+
207
+ Raises
208
+ ------
209
+ PyegeriaInvalidParameterException
210
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
211
+ PyegeriaAPIException
212
+ Raised by the server when an issue arises in processing a valid request
213
+ NotAuthorizedException
214
+ The principle specified by the user_id does not have authorization for the requested action
215
+ Notes
216
+ -----
217
+ This routine creates a new bearer token for the user and updates the object with it.
218
+ It uses Egeria's mechanisms to create a token. This is useful if an Egeria token expires.
219
+ A bearer token from another source can be set with the set_bearer_token() method.
220
+
221
+ """
222
+ if user_id is None:
223
+ user_id = self.user_id
224
+ if password is None:
225
+ password = self.user_pwd
226
+
227
+ url = f"{self.platform_url}/servers/{self.server_name}/api/token"
228
+ data = {"userId": user_id, "password": password}
229
+ async with AsyncClient(verify=enable_ssl_check) as client:
230
+ try:
231
+ response = await client.post(url, json=data, headers=self.headers)
232
+ token = response.text
233
+ except httpx.HTTPError as e:
234
+ print(e)
235
+ return "FAILED"
236
+
237
+ if token:
238
+ self.token_src = "Egeria"
239
+ self.headers["Authorization"] = f"Bearer {token}"
240
+ self.text_headers["Authorization"] = f"Bearer {token}"
241
+ return token
242
+ else:
243
+ additional_info = {"reason": "No token returned - request issue?"}
244
+ raise PyegeriaInvalidParameterException(None, None, additional_info)
245
+
246
+ def create_egeria_bearer_token(
247
+ self, user_id: str = None, password: str = None
248
+ ) -> str:
249
+ """Create and set an Egeria Server Bearer Token for the user
250
+ Parameters
251
+ ----------
252
+ user_id : str, optional
253
+ The user id to authenticate with. If None, then user_id from class instance used.
254
+ password : str, optional
255
+ The password for the user. If None, then user_pwd from class instance is used.
256
+
257
+ Returns
258
+ -------
259
+ token
260
+ The server bearer token for the specified user.
261
+
262
+ Raises
263
+ ------
264
+ PyegeriaInvalidParameterException
265
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
266
+ PyegeriaAPIException
267
+ Raised by the server when an issue arises in processing a valid request
268
+ NotAuthorizedException
269
+ The principle specified by the user_id does not have authorization for the requested action
270
+ Notes
271
+ -----
272
+ This routine creates a new bearer token for the user and updates the object with it.
273
+ It uses Egeria's mechanisms to create a token. This is useful if an Egeria token expires.
274
+ A bearer token from another source can be set with the set_bearer_token() method.
275
+
276
+ """
277
+ loop = asyncio.get_event_loop()
278
+ response = loop.run_until_complete(
279
+ self._async_create_egeria_bearer_token(user_id, password)
280
+ )
281
+ return response
282
+
283
+ async def _async_refresh_egeria_bearer_token(self) -> str:
284
+ """
285
+ Refreshes the Egeria bearer token. Async version.
286
+
287
+ This method is used to refresh the bearer token used for authentication with Egeria. It checks if the token
288
+ source is 'Egeria', and if the user ID and password are valid. If all conditions are met, it calls the
289
+ `create_egeria_bearer_token` method to create a new bearer token.
290
+
291
+ Returns
292
+ -------
293
+ str
294
+ The new platform bearer token.
295
+
296
+ Raises
297
+ ------
298
+ PyegeriaInvalidParameterException
299
+ If the token source is invalid or user credentials are missing.
300
+ """
301
+ if (
302
+ (self.token_src == "Egeria")
303
+ and validate_user_id(self.user_id)
304
+ and validate_name(self.user_pwd)
305
+ ):
306
+ token = await self._async_create_egeria_bearer_token(
307
+ self.user_id, self.user_pwd
308
+ )
309
+ return token
310
+ else:
311
+ additional_info = {"reason": "Invalid token source"}
312
+ raise PyegeriaInvalidParameterException(None, None, additional_info)
313
+
314
+ def refresh_egeria_bearer_token(self) -> str:
315
+ """
316
+ Refreshes the Egeria bearer token.
317
+
318
+ This method is used to refresh the bearer token used for authentication with Egeria. It checks if the token
319
+ source is 'Egeria', and if the user ID and password are valid. If all conditions are met, it calls the
320
+ `create_egeria_bearer_token` method to create a new bearer token.
321
+
322
+ Returns
323
+ -------
324
+ str
325
+ The new platform bearer token.
326
+
327
+ Raises
328
+ ------
329
+ PyegeriaInvalidParameterException
330
+ If the token source is invalid or user credentials are missing.
331
+ PyegeriaAPIException
332
+ Raised by the server when an issue arises in processing a valid request
333
+ PyegeriaNotAuthorizedException
334
+ The principle specified by the user_id does not have authorization for the requested action
335
+ """
336
+ loop = asyncio.get_event_loop()
337
+ token = loop.run_until_complete(self._async_refresh_egeria_bearer_token())
338
+ return token
339
+
340
+ def set_bearer_token(self, token: str) -> None:
341
+ """Set the Bearer Token for the client.
342
+
343
+ Parameters
344
+ ----------
345
+ token : str
346
+ A bearer token supplied to the method.
347
+
348
+ Raises
349
+ ------
350
+ PyegeriaInvalidParameterException
351
+ If the token is invalid.
352
+ """
353
+ validate_name(token)
354
+ self.headers["Authorization"] = f"Bearer {token}"
355
+ self.text_headers["Authorization"] = f"Bearer {token}"
356
+
357
+ def get_token(self) -> str:
358
+ """Retrieve and return the current bearer token.
359
+
360
+ Returns
361
+ -------
362
+ str
363
+ The current bearer token.
364
+ """
365
+ return self.text_headers["Authorization"]
366
+
367
+ async def async_get_platform_origin(self) -> str:
368
+ """Return the platform origin string if reachable. Async version.
369
+
370
+ Returns
371
+ -------
372
+ str
373
+ The platform origin string if reachable, otherwise an empty string.
374
+ """
375
+ origin_url = f"{self.platform_url}/api/about"
376
+ response = await self._async_make_request("GET", origin_url, is_json=False)
377
+ if response.status_code == 200:
378
+ text = response.text.strip()
379
+ logger.debug(f"Got response from {origin_url}\n Response: {text}")
380
+ return text
381
+ else:
382
+ logger.debug(f"Got response from {origin_url}\n status_code: {response.status_code}")
383
+ return ""
384
+
385
+
386
+ def get_platform_origin(self) -> str:
387
+ """Return the platform origin string if reachable.
388
+
389
+ Returns
390
+ -------
391
+ str
392
+ The platform origin string if reachable, otherwise an empty string.
393
+ """
394
+ loop = asyncio.get_event_loop()
395
+ response = loop.run_until_complete(self.async_get_platform_origin())
396
+ return response
397
+
398
+ # @logger.catch
399
+ def make_request(
400
+ self,
401
+ request_type: str,
402
+ endpoint: str,
403
+ payload: str | dict = None,
404
+ time_out: int = 30,
405
+ is_json: bool = True,
406
+ params: dict | None = None
407
+ ) -> Response | str:
408
+ """Make a synchronous request to the Egeria API.
409
+
410
+ Parameters
411
+ ----------
412
+ request_type : str
413
+ The type of HTTP request (e.g., 'GET', 'POST').
414
+ endpoint : str
415
+ The API endpoint URL.
416
+ payload : str | dict, optional
417
+ The request payload.
418
+ time_out : int, optional
419
+ The timeout for the request in seconds (default is 30).
420
+ is_json : bool, optional
421
+ Whether the payload is in JSON format (default is True).
422
+ params : dict, optional
423
+ Query parameters for the request.
424
+
425
+ Returns
426
+ -------
427
+ Response | str
428
+ The response from the API.
429
+
430
+ Raises
431
+ ------
432
+ PyegeriaException
433
+ If the request fails.
434
+ """
435
+ try:
436
+ loop = asyncio.get_running_loop()
437
+ if loop.is_running():
438
+ coro = self._async_make_request(request_type, endpoint, payload, time_out, is_json, params)
439
+ return asyncio.run_coroutine_threadsafe(coro, loop).result()
440
+ else:
441
+ return loop.run_until_complete(
442
+ self._async_make_request(request_type, endpoint, payload, time_out, is_json, params))
443
+ except RuntimeError:
444
+ # No running loop exists; run the coroutine
445
+ return asyncio.run(self._async_make_request(request_type, endpoint, payload, time_out, is_json, params))
446
+
447
+
448
+ async def _async_make_request(
449
+ self,
450
+ request_type: str,
451
+ endpoint: str,
452
+ payload: str | dict = None,
453
+ time_out: int = 30,
454
+ is_json: bool = True,
455
+ params: dict | None = None
456
+ ) -> Response | str:
457
+ """Make an asynchronous request to the Egeria API.
458
+
459
+ Parameters
460
+ ----------
461
+ request_type : str
462
+ The type of HTTP request (e.g., 'GET', 'POST').
463
+ endpoint : str
464
+ The API endpoint URL.
465
+ payload : str | dict, optional
466
+ The request payload.
467
+ time_out : int, optional
468
+ The timeout for the request in seconds (default is 30).
469
+ is_json : bool, optional
470
+ Whether the payload is in JSON format (default is True).
471
+ params : dict, optional
472
+ Query parameters for the request.
473
+
474
+ Returns
475
+ -------
476
+ Response | str
477
+ The response from the API.
478
+
479
+ Raises
480
+ ------
481
+ PyegeriaAPIException
482
+ If the server returns an error.
483
+ PyegeriaConnectionException
484
+ If there is a connection issue.
485
+ PyegeriaInvalidParameterException
486
+ If the request parameters are invalid.
487
+ """
488
+ context: dict = {}
489
+ context['class name'] = __class__.__name__
490
+ context['caller method'] = inspect.currentframe().f_back.f_code.co_name
491
+ response: Response = None # Initialize to None to avoid UnboundLocalError
492
+
493
+ try:
494
+ if request_type == "GET":
495
+ response = await self.session.get(
496
+ endpoint, params=params, headers=self.headers, timeout=time_out,
497
+ )
498
+
499
+ elif request_type == "POST":
500
+ if payload is None:
501
+ response = await self.session.post(
502
+ endpoint, headers=self.headers, timeout=time_out, params = params
503
+ )
504
+ elif type(payload) is dict:
505
+ response = await self.session.post(
506
+ endpoint, json=payload, headers=self.headers, timeout=time_out
507
+ )
508
+ elif type(payload) is str:
509
+ response = await self.session.post(
510
+ endpoint,
511
+ headers=self.headers,
512
+ content=payload,
513
+ timeout=time_out,
514
+ params=params
515
+ )
516
+ else:
517
+ raise TypeError(f"Invalid payload type {type(payload)}")
518
+
519
+
520
+ elif request_type == "POST-DATA":
521
+ if True:
522
+ response = await self.session.post(
523
+ endpoint, headers=self.headers, data=payload, timeout=time_out
524
+ )
525
+ elif request_type == "DELETE":
526
+ if True:
527
+ response = await self.session.delete(
528
+ endpoint, headers=self.headers, timeout=time_out
529
+ )
530
+ response.raise_for_status()
531
+
532
+ status_code = response.status_code
533
+
534
+ except (httpx.TimeoutException, httpcore.ConnectError, httpx.ConnectError) as e:
535
+ additional_info = {"endpoint": endpoint, "error_kind": "connection"}
536
+ raise PyegeriaConnectionException(context, additional_info, e)
537
+
538
+ except (HTTPStatusError, httpx.HTTPStatusError, httpx.RequestError) as e:
539
+ additional_info = {"userid": self.user_id}
540
+ if response is not None:
541
+ additional_info["reason"] = response.text
542
+
543
+ raise PyegeriaClientException(response, context, additional_info, e)
544
+
545
+ except Exception as e:
546
+ additional_info = {"userid": self.user_id}
547
+ if response is not None:
548
+ logger.error(f"Response error with code {response.status_code}")
549
+ else:
550
+ logger.error("Response object not available due to error")
551
+ raise PyegeriaUnknownException(response, context, additional_info, e)
552
+
553
+ if status_code in (200, 201):
554
+ try:
555
+ if is_json:
556
+ json_response = response.json()
557
+ related_http_code = json_response.get("relatedHTTPCode", 0)
558
+ if related_http_code == 200:
559
+ return response
560
+ else:
561
+ raise PyegeriaAPIException(response, context, additional_info=None)
562
+
563
+ else: # Not JSON - Text?
564
+ return response
565
+
566
+
567
+ except json.JSONDecodeError as e:
568
+ logger.error("Failed to decode JSON response from %s: %s", endpoint, response.text,
569
+ exc_info=True)
570
+ context['caught_exception'] = e
571
+ raise PyegeriaInvalidParameterException(
572
+ response, context, e=e
573
+ )