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.
- commands/__init__.py +24 -0
- commands/cat/Dr-Egeria_md-orig.py +2 -2
- commands/cat/__init__.py +1 -17
- commands/cat/collection_actions.py +197 -0
- commands/cat/dr_egeria_command_help.py +372 -0
- commands/cat/dr_egeria_jupyter.py +7 -7
- commands/cat/dr_egeria_md.py +27 -182
- commands/cat/exp_list_glossaries.py +11 -14
- commands/cat/get_asset_graph.py +37 -267
- commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
- commands/cat/get_project_dependencies.py +14 -14
- commands/cat/get_project_structure.py +15 -14
- commands/cat/get_tech_type_elements.py +16 -116
- commands/cat/glossary_actions.py +145 -298
- commands/cat/list_assets.py +3 -11
- commands/cat/list_cert_types.py +17 -63
- commands/cat/list_collections.py +46 -138
- commands/cat/list_deployed_catalogs.py +15 -27
- commands/cat/list_deployed_database_schemas.py +27 -43
- commands/cat/list_deployed_databases.py +16 -31
- commands/cat/list_deployed_servers.py +35 -54
- commands/cat/list_glossaries.py +18 -17
- commands/cat/list_projects.py +10 -12
- commands/cat/list_tech_type_elements.py +21 -37
- commands/cat/list_tech_types.py +13 -25
- commands/cat/list_terms.py +38 -79
- commands/cat/list_todos.py +4 -11
- commands/cat/list_user_ids.py +3 -10
- commands/cat/my_reports.py +559 -0
- commands/cat/run_report.py +394 -0
- commands/cat/run_report_orig.py +528 -0
- commands/cli/egeria.py +222 -247
- commands/cli/egeria_cat.py +68 -81
- commands/cli/egeria_my.py +13 -0
- commands/cli/egeria_ops.py +69 -74
- commands/cli/egeria_tech.py +17 -93
- commands/cli/ops_config.py +3 -6
- commands/{cat/list_categories.py → deprecated/list_data_designer.py} +53 -64
- commands/{cat/list_data_structures.py → deprecated/list_data_structures_full.py} +3 -6
- commands/deprecated/old_get_asset_graph.py +315 -0
- commands/my/__init__.py +0 -2
- commands/my/list_my_profile.py +27 -34
- commands/my/list_my_roles.py +1 -7
- commands/my/monitor_my_todos.py +1 -7
- commands/my/monitor_open_todos.py +6 -7
- commands/my/todo_actions.py +4 -5
- commands/ops/__init__.py +0 -2
- commands/ops/gov_server_actions.py +17 -21
- commands/ops/list_archives.py +17 -38
- commands/ops/list_catalog_targets.py +33 -40
- commands/ops/load_archive.py +35 -26
- commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
- commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
- commands/ops/monitor_engine_activity.py +79 -77
- commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
- commands/ops/monitor_platform_status.py +38 -50
- commands/ops/monitor_server_startup.py +6 -11
- commands/ops/monitor_server_status.py +7 -11
- commands/ops/orig_monitor_server_list.py +8 -8
- commands/ops/orig_monitor_server_status.py +1 -5
- commands/ops/refresh_integration_daemon.py +5 -5
- commands/ops/restart_integration_daemon.py +5 -5
- commands/ops/table_integ_daemon_status.py +6 -6
- commands/ops/x_engine_actions.py +7 -7
- commands/tech/__init__.py +0 -2
- commands/tech/{generic_actions.py → element_actions.py} +6 -11
- commands/tech/get_element_info.py +20 -29
- commands/tech/get_guid_info.py +23 -42
- commands/tech/get_tech_details.py +20 -35
- commands/tech/get_tech_type_template.py +28 -39
- commands/tech/list_all_om_type_elements.py +24 -30
- commands/tech/list_all_om_type_elements_x.py +22 -28
- commands/tech/list_all_related_elements.py +19 -28
- commands/tech/list_anchored_elements.py +22 -30
- commands/tech/list_asset_types.py +19 -24
- commands/tech/list_elements_by_classification_by_property_value.py +26 -32
- commands/tech/list_elements_by_property_value.py +19 -25
- commands/tech/list_elements_by_property_value_x.py +20 -28
- commands/tech/list_elements_for_classification.py +28 -41
- commands/tech/list_gov_action_processes.py +16 -27
- commands/tech/list_information_supply_chains.py +22 -30
- commands/tech/list_registered_services.py +14 -26
- commands/tech/list_related_elements_with_prop_value.py +15 -25
- commands/tech/list_related_specification.py +1 -4
- commands/tech/list_relationship_types.py +15 -25
- commands/tech/list_relationships.py +20 -36
- commands/tech/list_solution_blueprints.py +28 -33
- commands/tech/list_solution_components.py +23 -29
- commands/tech/list_solution_roles.py +21 -32
- commands/tech/list_tech_templates.py +51 -54
- commands/tech/list_valid_metadata_values.py +5 -9
- commands/tech/table_tech_templates.py +2 -6
- commands/tech/x_list_related_elements.py +1 -4
- examples/GeoSpatial Products Example.py +524 -0
- examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
- examples/Jupyter Notebooks/README.md +2 -0
- examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
- examples/Jupyter Notebooks/common/__init__.py +14 -0
- examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
- examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
- examples/Jupyter Notebooks/common/globals.ipynb +184 -0
- examples/Jupyter Notebooks/common/globals.py +154 -0
- examples/Jupyter Notebooks/common/orig_globals.py +152 -0
- examples/format_sets/all_format_sets.json +910 -0
- examples/format_sets/custom_format_sets.json +268 -0
- examples/format_sets/subset_format_sets.json +187 -0
- examples/format_sets_save_load_example.py +291 -0
- examples/jacquard_data_sets.py +129 -0
- examples/output_formats_example.py +193 -0
- examples/test_jacquard_data_sets.py +54 -0
- examples/test_jacquard_data_sets_scenarios.py +94 -0
- md_processing/__init__.py +90 -0
- md_processing/command_dispatcher.py +33 -0
- md_processing/command_mapping.py +221 -0
- md_processing/data/commands/commands_data_designer.json +537 -0
- md_processing/data/commands/commands_external_reference.json +733 -0
- md_processing/data/commands/commands_feedback.json +155 -0
- md_processing/data/commands/commands_general.json +204 -0
- md_processing/data/commands/commands_glossary.json +218 -0
- md_processing/data/commands/commands_governance.json +3678 -0
- md_processing/data/commands/commands_product_manager.json +865 -0
- md_processing/data/commands/commands_project.json +642 -0
- md_processing/data/commands/commands_solution_architect.json +366 -0
- md_processing/data/commands.json +17568 -0
- md_processing/data/commands_working.json +30641 -0
- md_processing/data/gened_report_specs.py +6584 -0
- md_processing/data/generated_format_sets.json +6533 -0
- md_processing/data/generated_format_sets_old.json +4137 -0
- md_processing/data/generated_format_sets_old.py +45 -0
- md_processing/dr_egeria.py +182 -0
- md_processing/md_commands/__init__.py +3 -0
- md_processing/md_commands/data_designer_commands.py +1276 -0
- md_processing/md_commands/ext_ref_commands.py +530 -0
- md_processing/md_commands/feedback_commands.py +726 -0
- md_processing/md_commands/glossary_commands.py +684 -0
- md_processing/md_commands/governance_officer_commands.py +600 -0
- md_processing/md_commands/product_manager_commands.py +1266 -0
- md_processing/md_commands/project_commands.py +383 -0
- md_processing/md_commands/solution_architect_commands.py +1184 -0
- md_processing/md_commands/view_commands.py +295 -0
- md_processing/md_processing_utils/__init__.py +4 -0
- md_processing/md_processing_utils/common_md_proc_utils.py +1249 -0
- md_processing/md_processing_utils/common_md_utils.py +578 -0
- md_processing/md_processing_utils/determine_width.py +103 -0
- md_processing/md_processing_utils/extraction_utils.py +547 -0
- md_processing/md_processing_utils/gen_report_specs.py +643 -0
- md_processing/md_processing_utils/generate_dr_help.py +193 -0
- md_processing/md_processing_utils/generate_md_cmd_templates.py +144 -0
- md_processing/md_processing_utils/generate_md_templates.py +83 -0
- md_processing/md_processing_utils/md_processing_constants.py +1228 -0
- md_processing/md_processing_utils/message_constants.py +19 -0
- pyegeria/__init__.py +201 -443
- pyegeria/core/__init__.py +40 -0
- pyegeria/core/_base_platform_client.py +574 -0
- pyegeria/core/_base_server_client.py +573 -0
- pyegeria/core/_exceptions.py +457 -0
- pyegeria/core/_globals.py +60 -0
- pyegeria/core/_server_client.py +6073 -0
- pyegeria/core/_validators.py +257 -0
- pyegeria/core/config.py +654 -0
- pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
- pyegeria/core/load_config.py +37 -0
- pyegeria/core/logging_configuration.py +207 -0
- pyegeria/core/mcp_adapter.py +144 -0
- pyegeria/core/mcp_server.py +212 -0
- pyegeria/core/utils.py +405 -0
- pyegeria/deprecated/__init__.py +0 -0
- pyegeria/{_client.py → deprecated/_client.py} +62 -24
- pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
- pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1988 -1878
- pyegeria/deprecated/output_formatter_with_machine_keys.py +1127 -0
- pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +216 -229
- pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
- pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
- pyegeria/egeria_cat_client.py +25 -51
- pyegeria/egeria_client.py +140 -98
- pyegeria/egeria_config_client.py +48 -24
- pyegeria/egeria_tech_client.py +170 -83
- pyegeria/models/__init__.py +150 -0
- pyegeria/models/collection_models.py +168 -0
- pyegeria/models/models.py +654 -0
- pyegeria/omvs/__init__.py +84 -0
- pyegeria/omvs/action_author.py +342 -0
- pyegeria/omvs/actor_manager.py +5980 -0
- pyegeria/omvs/asset_catalog.py +842 -0
- pyegeria/omvs/asset_maker.py +2736 -0
- pyegeria/omvs/automated_curation.py +4403 -0
- pyegeria/omvs/classification_manager.py +11213 -0
- pyegeria/omvs/collection_manager.py +5780 -0
- pyegeria/omvs/community_matters_omvs.py +468 -0
- pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
- pyegeria/{data_designer_omvs.py → omvs/data_designer.py} +1991 -1691
- pyegeria/omvs/data_discovery.py +869 -0
- pyegeria/omvs/data_engineer.py +372 -0
- pyegeria/omvs/digital_business.py +1133 -0
- pyegeria/omvs/external_links.py +1752 -0
- pyegeria/omvs/feedback_manager.py +834 -0
- pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
- pyegeria/omvs/glossary_manager.py +3231 -0
- pyegeria/omvs/governance_officer.py +3009 -0
- pyegeria/omvs/lineage_linker.py +314 -0
- pyegeria/omvs/location_arena.py +1525 -0
- pyegeria/omvs/metadata_expert.py +668 -0
- pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
- pyegeria/omvs/my_profile.py +1042 -0
- pyegeria/omvs/notification_manager.py +358 -0
- pyegeria/omvs/people_organizer.py +394 -0
- pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
- pyegeria/omvs/product_manager.py +1825 -0
- pyegeria/omvs/project_manager.py +1907 -0
- pyegeria/omvs/reference_data.py +1140 -0
- pyegeria/omvs/registered_info.py +334 -0
- pyegeria/omvs/runtime_manager.py +2817 -0
- pyegeria/omvs/schema_maker.py +446 -0
- pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
- pyegeria/omvs/solution_architect.py +6490 -0
- pyegeria/omvs/specification_properties.py +37 -0
- pyegeria/omvs/subject_area.py +1042 -0
- pyegeria/omvs/template_manager_omvs.py +236 -0
- pyegeria/omvs/time_keeper.py +1761 -0
- pyegeria/omvs/valid_metadata.py +3221 -0
- pyegeria/omvs/valid_metadata_lists.py +37 -0
- pyegeria/omvs/valid_type_lists.py +37 -0
- pyegeria/view/__init__.py +28 -0
- pyegeria/view/_output_format_models.py +514 -0
- pyegeria/view/_output_formats.py +14 -0
- pyegeria/view/base_report_formats.py +2719 -0
- pyegeria/view/dr_egeria_reports.py +56 -0
- pyegeria/view/format_set_executor.py +397 -0
- pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
- pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
- pyegeria/view/output_formatter.py +1297 -0
- pyegeria-5.5.3.3.dist-info/METADATA +218 -0
- pyegeria-5.5.3.3.dist-info/RECORD +241 -0
- {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
- pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
- pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
- commands/cat/.DS_Store +0 -0
- commands/cat/README.md +0 -16
- commands/cli/txt_custom_v2.tcss +0 -19
- commands/my/README.md +0 -17
- commands/ops/README.md +0 -24
- commands/ops/monitor_asset_events.py +0 -108
- commands/tech/README.md +0 -24
- pyegeria/.DS_Store +0 -0
- pyegeria/README.md +0 -35
- pyegeria/_globals.py +0 -47
- pyegeria/_validators.py +0 -385
- pyegeria/asset_catalog_omvs.py +0 -864
- pyegeria/automated_curation_omvs.py +0 -3765
- pyegeria/collection_manager_omvs.py +0 -2744
- pyegeria/dr.egeria spec.md +0 -9
- pyegeria/egeria_my_client.py +0 -56
- pyegeria/feedback_manager_omvs.py +0 -4573
- pyegeria/glossary_browser_omvs.py +0 -3728
- pyegeria/glossary_manager_omvs.py +0 -2440
- pyegeria/m_test.py +0 -118
- pyegeria/md_processing_helpers.py +0 -58
- pyegeria/md_processing_utils_orig.py +0 -1103
- pyegeria/metadata_explorer_omvs.py +0 -2326
- pyegeria/my_profile_omvs.py +0 -1022
- pyegeria/output_formatter.py +0 -389
- pyegeria/project_manager_omvs.py +0 -1933
- pyegeria/registered_info.py +0 -167
- pyegeria/solution_architect_omvs.py +0 -2156
- pyegeria/template_manager_omvs.py +0 -1414
- pyegeria/utils.py +0 -197
- pyegeria-5.3.9.9.3.dist-info/METADATA +0 -72
- pyegeria-5.3.9.9.3.dist-info/RECORD +0 -143
- pyegeria-5.3.9.9.3.dist-info/entry_points.txt +0 -99
- /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
- {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
|
+
)
|