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