pyegeria 5.4.7.3__py3-none-any.whl → 5.4.7.5__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.
- commands/cat/dr_egeria_md.py +1 -1
- commands/cat/list_format_set.py +6 -1
- commands/ops/__init__.py +0 -2
- commands/ops/list_catalog_targets.py +17 -15
- commands/ops/load_archive.py +3 -3
- commands/ops/monitor_engine_activity.py +1 -1
- commands/ops/monitor_engine_activity_c.py +1 -1
- commands/tech/__init__.py +0 -2
- commands/tech/list_gov_action_processes.py +4 -8
- md_processing/dr_egeria.py +1 -1
- md_processing/md_commands/ext_ref_commands.py +1 -2
- md_processing/md_commands/glossary_commands.py +1 -2
- md_processing/md_commands/project_commands.py +1 -2
- pyegeria/__init__.py +4 -96
- pyegeria/_client_new.py +658 -64
- pyegeria/_globals.py +95 -1
- pyegeria/_output_formats.py +1 -1
- pyegeria/asset_catalog_omvs.py +1 -1
- pyegeria/automated_curation.py +788 -857
- pyegeria/classification_manager.py +7212 -0
- pyegeria/classification_manager_omvs.py +1989 -1853
- pyegeria/collection_manager.py +14 -2
- pyegeria/data_designer.py +1 -2
- pyegeria/egeria_tech_client.py +3 -0
- pyegeria/external_references.py +1 -1
- pyegeria/format_set_executor.py +8 -9
- pyegeria/full_omag_server_config.py +1 -1
- pyegeria/mcp_adapter.py +1 -1
- pyegeria/mcp_server.py +36 -21
- pyegeria/md_processing_utils.py +3 -3
- pyegeria/md_processing_utils_orig.py +3 -3
- pyegeria/mermaid_utilities.py +0 -152
- pyegeria/models.py +5 -0
- pyegeria/output_formatter.py +1 -1
- pyegeria/project_manager.py +8 -0
- pyegeria/reference_data.py +4 -0
- pyegeria/runtime_manager_omvs.py +1 -1
- pyegeria/solution_architect.py +1 -1
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/METADATA +1 -1
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/RECORD +44 -44
- pyegeria/md_processing_helpers.py +0 -58
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/WHEEL +0 -0
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/entry_points.txt +0 -0
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/licenses/LICENSE +0 -0
- {pyegeria-5.4.7.3.dist-info → pyegeria-5.4.7.5.dist-info}/top_level.txt +0 -0
pyegeria/_client_new.py
CHANGED
@@ -12,6 +12,7 @@ import inspect
|
|
12
12
|
import json
|
13
13
|
import os
|
14
14
|
import re
|
15
|
+
import sys
|
15
16
|
from collections.abc import Callable
|
16
17
|
from typing import Any
|
17
18
|
|
@@ -26,7 +27,7 @@ from pyegeria._exceptions_new import (
|
|
26
27
|
PyegeriaAPIException, PyegeriaConnectionException, PyegeriaInvalidParameterException,
|
27
28
|
PyegeriaUnknownException, PyegeriaClientException
|
28
29
|
)
|
29
|
-
from pyegeria._globals import enable_ssl_check, max_paging_size, NO_ELEMENTS_FOUND
|
30
|
+
from pyegeria._globals import enable_ssl_check, max_paging_size, NO_ELEMENTS_FOUND, default_time_out
|
30
31
|
from pyegeria._validators import (
|
31
32
|
validate_name,
|
32
33
|
validate_server_name,
|
@@ -34,9 +35,14 @@ from pyegeria._validators import (
|
|
34
35
|
validate_user_id,
|
35
36
|
)
|
36
37
|
from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
TemplateRequestBody, UpdateStatusRequestBody, UpdateElementRequestBody,
|
39
|
+
NewRelationshipRequestBody,
|
40
|
+
DeleteRequestBody, UpdateRelationshipRequestBody, ResultsRequestBody,
|
41
|
+
NewClassificationRequestBody,
|
42
|
+
DeleteElementRequestBody, DeleteRelationshipRequestBody, DeleteClassificationRequestBody,
|
43
|
+
LevelIdentifierQueryBody)
|
44
|
+
|
45
|
+
from pyegeria.output_formatter import populate_common_columns, resolve_output_formats, generate_output
|
40
46
|
from pyegeria.utils import body_slimmer, dynamic_catch
|
41
47
|
|
42
48
|
...
|
@@ -156,6 +162,8 @@ class Client2:
|
|
156
162
|
self._template_request_adapter = TypeAdapter(TemplateRequestBody)
|
157
163
|
self._update_relationship_request_adapter = TypeAdapter(UpdateRelationshipRequestBody)
|
158
164
|
self._results_request_adapter = TypeAdapter(ResultsRequestBody)
|
165
|
+
self._level_identifier_query_body = TypeAdapter(LevelIdentifierQueryBody)
|
166
|
+
|
159
167
|
try:
|
160
168
|
result = self.check_connection()
|
161
169
|
logger.info(f"client initialized, platform origin is: {result}")
|
@@ -203,7 +211,7 @@ class Client2:
|
|
203
211
|
return
|
204
212
|
|
205
213
|
async def _async_create_egeria_bearer_token(
|
206
|
-
self, user_id: str
|
214
|
+
self, user_id: str , password: str
|
207
215
|
) -> str:
|
208
216
|
"""Create and set an Egeria Bearer Token for the user. Async version
|
209
217
|
Parameters
|
@@ -234,10 +242,8 @@ class Client2:
|
|
234
242
|
|
235
243
|
"""
|
236
244
|
if user_id is None:
|
237
|
-
validate_user_id(self.user_id)
|
238
245
|
user_id = self.user_id
|
239
246
|
if password is None:
|
240
|
-
validate_name(self.user_pwd)
|
241
247
|
password = self.user_pwd
|
242
248
|
|
243
249
|
url = f"{self.platform_url}/api/token"
|
@@ -556,56 +562,6 @@ class Client2:
|
|
556
562
|
response, context, e=e
|
557
563
|
)
|
558
564
|
|
559
|
-
def build_global_guid_lists(self) -> None:
|
560
|
-
global template_guids, integration_guids
|
561
|
-
|
562
|
-
self.create_egeria_bearer_token(self.user_id, self.user_pwd)
|
563
|
-
# get all technology types
|
564
|
-
url = (
|
565
|
-
f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/automated-curation/technology-types/"
|
566
|
-
f"by-search-string?startFrom=0&pageSize=0&startsWith=false&"
|
567
|
-
f"endsWith=false&ignoreCase=true"
|
568
|
-
)
|
569
|
-
body = {"filter": ""}
|
570
|
-
|
571
|
-
response = self.make_request("POST", url, body)
|
572
|
-
tech_types = response.json().get("elements", "no tech found")
|
573
|
-
if type(tech_types) is list:
|
574
|
-
for tech_type in tech_types:
|
575
|
-
# get tech type details
|
576
|
-
display_name = tech_type["name"]
|
577
|
-
|
578
|
-
url = (f"{self.platform_url}/servers/"
|
579
|
-
f"{self.server_name}/api/open-metadata/automated-curation/technology-types/by-name")
|
580
|
-
body = {"filter": display_name}
|
581
|
-
response = self.make_request("POST", url, body)
|
582
|
-
details = response.json().get("element", "no type found")
|
583
|
-
if type(details) is str:
|
584
|
-
continue
|
585
|
-
# get templates and update the template_guids global
|
586
|
-
templates = details.get("catalogTemplates", "Not Found")
|
587
|
-
if type(templates) is str:
|
588
|
-
template_guids[display_name] = None
|
589
|
-
else:
|
590
|
-
for template in templates:
|
591
|
-
template_name = template.get("name", None)
|
592
|
-
template_guid = template["relatedElement"]["guid"]
|
593
|
-
template_guids[template_name] = template_guid
|
594
|
-
# print(f"Added {template_name} template with GUID {template_guids[template_name]}")
|
595
|
-
|
596
|
-
# Now find the integration connector guids
|
597
|
-
resource_list = details.get("resourceList", " ")
|
598
|
-
if type(resource_list) is str:
|
599
|
-
integration_guids[display_name] = None
|
600
|
-
else:
|
601
|
-
for resource in resource_list:
|
602
|
-
resource_guid = resource["relatedElement"]["guid"]
|
603
|
-
resource_type = resource["relatedElement"]["type"]["typeName"]
|
604
|
-
if resource_type == "IntegrationConnector":
|
605
|
-
integration_guids[display_name] = resource_guid
|
606
|
-
# print(f"Added {display_name} integration connector with GUID {integration_guids[
|
607
|
-
# display_name]}")
|
608
|
-
|
609
565
|
async def __async_get_guid__(
|
610
566
|
self,
|
611
567
|
guid: str = None,
|
@@ -639,7 +595,7 @@ class Client2:
|
|
639
595
|
}
|
640
596
|
url = (
|
641
597
|
f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/classification-manager/"
|
642
|
-
f"elements/guid-by-unique-name
|
598
|
+
f"elements/guid-by-unique-name"
|
643
599
|
)
|
644
600
|
|
645
601
|
result = await self._async_make_request("POST", url, body_slimmer(body))
|
@@ -691,6 +647,9 @@ class Client2:
|
|
691
647
|
f"qualified_name={qualified_name}, tech_type={tech_type}")
|
692
648
|
}
|
693
649
|
raise PyegeriaInvalidParameterException(None, None, additional_info)
|
650
|
+
#
|
651
|
+
# Include basic functions for finding elements and relationships.
|
652
|
+
#
|
694
653
|
|
695
654
|
def __get_guid__(
|
696
655
|
self,
|
@@ -718,6 +677,11 @@ class Client2:
|
|
718
677
|
)
|
719
678
|
return result
|
720
679
|
|
680
|
+
|
681
|
+
|
682
|
+
|
683
|
+
|
684
|
+
|
721
685
|
def __create_qualified_name__(self, type: str, display_name: str, local_qualifier: str = None,
|
722
686
|
version_identifier: str = None) -> str:
|
723
687
|
"""Helper function to create a qualified name for a given type and display name.
|
@@ -734,10 +698,378 @@ class Client2:
|
|
734
698
|
q_name = f"{q_name}::{version_identifier}"
|
735
699
|
return q_name
|
736
700
|
|
737
|
-
async def
|
701
|
+
async def _async_get_relationships_with_property_value(
|
702
|
+
self,
|
703
|
+
relationship_type: str,
|
704
|
+
property_value: str,
|
705
|
+
property_names: [str],
|
706
|
+
effective_time: str = None,
|
707
|
+
for_lineage: bool = None,
|
708
|
+
for_duplicate_processing: bool = None,
|
709
|
+
start_from: int = 0,
|
710
|
+
page_size: int = max_paging_size,
|
711
|
+
time_out: int = default_time_out,
|
712
|
+
) -> list | str:
|
713
|
+
"""
|
714
|
+
Retrieve relationships of the requested relationship type name and with the requested a value found in
|
715
|
+
one of the relationship's properties specified. The value must match exactly. Async version.
|
716
|
+
|
717
|
+
https://egeria-project.org/types/
|
718
|
+
|
719
|
+
Parameters
|
720
|
+
----------
|
721
|
+
relationship_type: str
|
722
|
+
- the type of relationship to navigate to related elements
|
723
|
+
property_value: str
|
724
|
+
- property value to be searched.
|
725
|
+
property_names: [str]
|
726
|
+
- property names to search in.
|
727
|
+
effective_time: str, default = None
|
728
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
729
|
+
for_lineage: bool, default is set by server
|
730
|
+
- determines if elements classified as Memento should be returned - normally false
|
731
|
+
for_duplicate_processing: bool, default is set by server
|
732
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
733
|
+
start_from: int, default = 0
|
734
|
+
- index of the list to start from (0 for start).
|
735
|
+
page_size
|
736
|
+
- maximum number of elements to return.
|
737
|
+
|
738
|
+
|
739
|
+
time_out: int, default = default_time_out
|
740
|
+
- http request timeout for this request
|
741
|
+
|
742
|
+
Returns
|
743
|
+
-------
|
744
|
+
[dict] | str
|
745
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
746
|
+
|
747
|
+
Raises
|
748
|
+
------
|
749
|
+
InvalidParameterException
|
750
|
+
one of the parameters is null or invalid or
|
751
|
+
PropertyServerException
|
752
|
+
There is a problem adding the element properties to the metadata repository or
|
753
|
+
UserNotAuthorizedException
|
754
|
+
the requesting user is not authorized to issue this request.
|
755
|
+
"""
|
756
|
+
|
757
|
+
|
758
|
+
|
759
|
+
body = {
|
760
|
+
"class": "FindPropertyNamesProperties",
|
761
|
+
"openMetadataType": relationship_type,
|
762
|
+
"propertyValue": property_value,
|
763
|
+
"propertyNames": property_names,
|
764
|
+
"effectiveTime": effective_time,
|
765
|
+
}
|
766
|
+
|
767
|
+
url = (
|
768
|
+
f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/classification-manager/relationships/"
|
769
|
+
f"with-exact-property-value"
|
770
|
+
)
|
771
|
+
|
772
|
+
response: Response = await self._async_make_request(
|
773
|
+
"POST", url, body_slimmer(body), time_out=time_out
|
774
|
+
)
|
775
|
+
rels = response.json().get("relationships", NO_ELEMENTS_FOUND)
|
776
|
+
if type(rels) is list:
|
777
|
+
if len(rels) == 0:
|
778
|
+
return NO_ELEMENTS_FOUND
|
779
|
+
return rels
|
780
|
+
|
781
|
+
def get_relationships_with_property_value(
|
782
|
+
self,
|
783
|
+
relationship_type: str,
|
784
|
+
property_value: str,
|
785
|
+
property_names: [str],
|
786
|
+
effective_time: str = None,
|
787
|
+
for_lineage: bool = None,
|
788
|
+
for_duplicate_processing: bool = None,
|
789
|
+
start_from: int = 0,
|
790
|
+
page_size: int = max_paging_size,
|
791
|
+
time_out: int = default_time_out,
|
792
|
+
) -> list | str:
|
793
|
+
"""
|
794
|
+
Retrieve relationships of the requested relationship type name and with the requested a value found in
|
795
|
+
one of the relationship's properties specified. The value must match exactly.
|
796
|
+
|
797
|
+
Parameters
|
798
|
+
----------
|
799
|
+
relationship_type: str
|
800
|
+
- the type of relationship to navigate to related elements
|
801
|
+
property_value: str
|
802
|
+
- property value to be searched.
|
803
|
+
property_names: [str]
|
804
|
+
- property names to search in.
|
805
|
+
effective_time: str, default = None
|
806
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
807
|
+
for_lineage: bool, default is set by server
|
808
|
+
- determines if elements classified as Memento should be returned - normally false
|
809
|
+
for_duplicate_processing: bool, default is set by server
|
810
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
811
|
+
start_from: int, default = 0
|
812
|
+
- index of the list to start from (0 for start).
|
813
|
+
page_size
|
814
|
+
- maximum number of elements to return.
|
815
|
+
|
816
|
+
|
817
|
+
time_out: int, default = default_time_out
|
818
|
+
- http request timeout for this request
|
819
|
+
|
820
|
+
Returns
|
821
|
+
-------
|
822
|
+
[dict] | str
|
823
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
824
|
+
|
825
|
+
Raises
|
826
|
+
------
|
827
|
+
InvalidParameterException
|
828
|
+
one of the parameters is null or invalid or
|
829
|
+
PropertyServerException
|
830
|
+
There is a problem adding the element properties to the metadata repository or
|
831
|
+
UserNotAuthorizedException
|
832
|
+
the requesting user is not authorized to issue this request.
|
833
|
+
"""
|
834
|
+
|
835
|
+
loop = asyncio.get_event_loop()
|
836
|
+
response = loop.run_until_complete(
|
837
|
+
self._async_get_relationships_with_property_value(
|
838
|
+
relationship_type,
|
839
|
+
property_value,
|
840
|
+
property_names,
|
841
|
+
effective_time,
|
842
|
+
for_lineage,
|
843
|
+
for_duplicate_processing,
|
844
|
+
start_from,
|
845
|
+
page_size,
|
846
|
+
time_out,
|
847
|
+
)
|
848
|
+
)
|
849
|
+
return response
|
850
|
+
|
851
|
+
|
852
|
+
async def async_get_elements_by_property_value(
|
853
|
+
self,
|
854
|
+
property_value: str,
|
855
|
+
property_names: [str],
|
856
|
+
metadata_element_type_name: str = None,
|
857
|
+
effective_time: str = None,
|
858
|
+
for_lineage: bool = None,
|
859
|
+
for_duplicate_processing: bool = None,
|
860
|
+
start_from: int = 0,
|
861
|
+
page_size: int = 0,
|
862
|
+
time_out: int = default_time_out,
|
863
|
+
) -> list | str:
|
864
|
+
"""
|
865
|
+
Retrieve elements by a value found in one of the properties specified. The value must match exactly.
|
866
|
+
An open metadata type name may be supplied to restrict the results. Async version.
|
867
|
+
|
868
|
+
https://egeria-project.org/types/
|
869
|
+
|
870
|
+
Parameters
|
871
|
+
----------
|
872
|
+
property_value: str
|
873
|
+
- property value to be searched.
|
874
|
+
property_names: [str]
|
875
|
+
- property names to search in.
|
876
|
+
metadata_element_type_name : str, default = None
|
877
|
+
- open metadata type to be used to restrict the search
|
878
|
+
effective_time: str, default = None
|
879
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
880
|
+
for_lineage: bool, default is set by server
|
881
|
+
- determines if elements classified as Memento should be returned - normally false
|
882
|
+
for_duplicate_processing: bool, default is set by server
|
883
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
884
|
+
start_from: int, default = 0
|
885
|
+
- index of the list to start from (0 for start).
|
886
|
+
page_size
|
887
|
+
- maximum number of elements to return.
|
888
|
+
|
889
|
+
|
890
|
+
time_out: int, default = default_time_out
|
891
|
+
- http request timeout for this request
|
892
|
+
|
893
|
+
Returns
|
894
|
+
-------
|
895
|
+
[dict] | str
|
896
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
897
|
+
|
898
|
+
Raises
|
899
|
+
------
|
900
|
+
PyegeriaException
|
901
|
+
"""
|
902
|
+
|
903
|
+
body = {
|
904
|
+
"class": "FindPropertyNamesProperties",
|
905
|
+
"metadataElementTypeName": metadata_element_type_name,
|
906
|
+
"propertyValue": property_value,
|
907
|
+
"propertyNames": property_names,
|
908
|
+
"effectiveTime": effective_time,
|
909
|
+
"startFrom": start_from,
|
910
|
+
"pageSize": page_size,
|
911
|
+
"forLineage": for_lineage,
|
912
|
+
"forDuplicateProcessing": for_duplicate_processing
|
913
|
+
}
|
914
|
+
|
915
|
+
url = f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/classification-explorer/elements/by-exact-property-value"
|
916
|
+
|
917
|
+
response: Response = await self._async_make_request(
|
918
|
+
"POST", url, body_slimmer(body), time_out=time_out
|
919
|
+
)
|
920
|
+
|
921
|
+
elements = response.json().get("elements", NO_ELEMENTS_FOUND)
|
922
|
+
if type(elements) is list:
|
923
|
+
if len(elements) == 0:
|
924
|
+
return NO_ELEMENTS_FOUND
|
925
|
+
return elements
|
926
|
+
|
927
|
+
def get_elements_by_property_value(
|
928
|
+
self,
|
929
|
+
property_value: str,
|
930
|
+
property_names: [str],
|
931
|
+
metadata_element_type_name: str = None,
|
932
|
+
effective_time: str = None,
|
933
|
+
for_lineage: bool = None,
|
934
|
+
for_duplicate_processing: bool = None,
|
935
|
+
start_from: int = 0,
|
936
|
+
page_size: int = 0,
|
937
|
+
time_out: int = default_time_out,
|
938
|
+
output_format: str = "JSON",
|
939
|
+
output_format_set: dict | str = None,
|
940
|
+
) -> list | str:
|
941
|
+
"""
|
942
|
+
Retrieve elements by a value found in one of the properties specified. The value must match exactly.
|
943
|
+
An open metadata type name may be supplied to restrict the results.
|
944
|
+
|
945
|
+
https://egeria-project.org/types/
|
946
|
+
|
947
|
+
Parameters
|
948
|
+
----------
|
949
|
+
property_value: str
|
950
|
+
- property value to be searched.
|
951
|
+
property_names: [str]
|
952
|
+
- property names to search in.
|
953
|
+
metadata_element_type_name : str, default = None
|
954
|
+
- open metadata type to be used to restrict the search
|
955
|
+
effective_time: str, default = None
|
956
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
957
|
+
for_lineage: bool, default is set by server
|
958
|
+
- determines if elements classified as Memento should be returned - normally false
|
959
|
+
for_duplicate_processing: bool, default is set by server
|
960
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
961
|
+
start_from: int, default = 0
|
962
|
+
- index of the list to start from (0 for start).
|
963
|
+
page_size
|
964
|
+
- maximum number of elements to return.
|
965
|
+
time_out: int, default = default_time_out
|
966
|
+
- http request timeout for this request
|
967
|
+
output_format: str, default = "JSON"
|
968
|
+
- Type of output to return.
|
969
|
+
output_format_set: dict | str, default = None
|
970
|
+
- Output format set to use. If None, the default output format set is used.
|
971
|
+
|
972
|
+
Returns
|
973
|
+
-------
|
974
|
+
[dict] | str
|
975
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
976
|
+
|
977
|
+
Raises
|
978
|
+
------
|
979
|
+
PyegeriaException.
|
980
|
+
"""
|
981
|
+
|
982
|
+
loop = asyncio.get_event_loop()
|
983
|
+
response = loop.run_until_complete(
|
984
|
+
self.async_get_elements_by_property_value(
|
985
|
+
property_value,
|
986
|
+
property_names,
|
987
|
+
metadata_element_type_name,
|
988
|
+
effective_time,
|
989
|
+
for_lineage,
|
990
|
+
for_duplicate_processing,
|
991
|
+
start_from,
|
992
|
+
page_size,
|
993
|
+
time_out,
|
994
|
+
)
|
995
|
+
)
|
996
|
+
return response
|
997
|
+
|
998
|
+
async def async_get_guid_for_name(
|
999
|
+
self, name: str, property_name: [str] = ["qualifiedName","displayName"], type_name: str = "ValidMetadataValue"
|
1000
|
+
|
1001
|
+
) -> list | str:
|
1002
|
+
"""
|
1003
|
+
Retrieve the guid associated with the supplied element name.
|
1004
|
+
If more than one element returned, an exception is thrown. Async version.
|
1005
|
+
|
1006
|
+
Parameters
|
1007
|
+
----------
|
1008
|
+
name: str
|
1009
|
+
- element name to be searched.
|
1010
|
+
property_name: [str], default = ["qualifiedName","displayName"]
|
1011
|
+
- propertys to search in.
|
1012
|
+
type_name: str, default = "ValidMetadataValue"
|
1013
|
+
- metadata element type name to be used to restrict the search
|
1014
|
+
Returns
|
1015
|
+
-------
|
1016
|
+
str
|
1017
|
+
Returns the guid of the element.
|
1018
|
+
|
1019
|
+
Raises
|
1020
|
+
------
|
1021
|
+
PyegeriaException
|
1022
|
+
"""
|
1023
|
+
|
1024
|
+
elements = await self.async_get_elements_by_property_value(
|
1025
|
+
name, property_name, type_name
|
1026
|
+
)
|
1027
|
+
|
1028
|
+
if type(elements) is list:
|
1029
|
+
if len(elements) == 0:
|
1030
|
+
return NO_ELEMENTS_FOUND
|
1031
|
+
elif len(elements) > 1:
|
1032
|
+
raise Exception("Multiple elements found for supplied name!")
|
1033
|
+
elif len(elements) == 1:
|
1034
|
+
return elements[0]["elementHeader"]["guid"]
|
1035
|
+
return elements
|
1036
|
+
|
1037
|
+
def get_guid_for_name(
|
1038
|
+
self, name: str, property_name: [str] = ["qualifiedName","displayName"], type_name: str = "ValidMetadataValue"
|
1039
|
+
) -> list | str:
|
738
1040
|
"""
|
739
|
-
|
740
|
-
|
1041
|
+
Retrieve the guid associated with the supplied element name.
|
1042
|
+
If more than one element returned, an exception is thrown.
|
1043
|
+
|
1044
|
+
Parameters
|
1045
|
+
----------
|
1046
|
+
name: str
|
1047
|
+
- element name to be searched.
|
1048
|
+
property_name: [str], default = ["qualifiedName","displayName"]
|
1049
|
+
- propertys to search in.
|
1050
|
+
type_name: str, default = "ValidMetadataValue"
|
1051
|
+
- metadata element type name to be used to restrict the search
|
1052
|
+
Returns
|
1053
|
+
-------
|
1054
|
+
str
|
1055
|
+
Returns the guid of the element.
|
1056
|
+
|
1057
|
+
Raises
|
1058
|
+
------
|
1059
|
+
PyegeriaExeception
|
1060
|
+
"""
|
1061
|
+
|
1062
|
+
loop = asyncio.get_event_loop()
|
1063
|
+
response = loop.run_until_complete(
|
1064
|
+
self.async_get_guid_for_name(name, property_name, type_name)
|
1065
|
+
)
|
1066
|
+
return response
|
1067
|
+
|
1068
|
+
|
1069
|
+
async def async_get_element_by_guid_(self, element_guid: str) -> dict | str:
|
1070
|
+
"""
|
1071
|
+
Simplified, internal version of get_element_by_guid found in Classification Manager.
|
1072
|
+
Retrieve an element by its guid. Async version.
|
741
1073
|
|
742
1074
|
Parameters
|
743
1075
|
----------
|
@@ -764,7 +1096,7 @@ class Client2:
|
|
764
1096
|
"effectiveTime": None,
|
765
1097
|
}
|
766
1098
|
|
767
|
-
url = (f"{self.platform_url}/servers/{self.
|
1099
|
+
url = (f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/classification-manager/elements/"
|
768
1100
|
f"{element_guid}?forLineage=false&forDuplicateProcessing=false")
|
769
1101
|
|
770
1102
|
response: Response = await self._async_make_request("POST", url, body_slimmer(body))
|
@@ -773,6 +1105,210 @@ class Client2:
|
|
773
1105
|
|
774
1106
|
return elements
|
775
1107
|
|
1108
|
+
async def async_get_related_elements_with_property_value(
|
1109
|
+
self,
|
1110
|
+
element_guid: str,
|
1111
|
+
relationship_type: str,
|
1112
|
+
property_value: str,
|
1113
|
+
property_names: [str],
|
1114
|
+
metadata_element_type_name: str = None,
|
1115
|
+
start_at_end: int = 1,
|
1116
|
+
effective_time: str = None,
|
1117
|
+
for_lineage: bool = None,
|
1118
|
+
for_duplicate_processing: bool = None,
|
1119
|
+
start_from: int = 0,
|
1120
|
+
page_size: int = 0,
|
1121
|
+
time_out: int = default_time_out,
|
1122
|
+
) -> list | str:
|
1123
|
+
"""
|
1124
|
+
Retrieve elements linked via the requested relationship type name and with the requested a value found in one of
|
1125
|
+
the classification's properties specified. The value must match exactly. An open metadata type name may be
|
1126
|
+
supplied to restrict the types of elements returned. Async version.
|
1127
|
+
|
1128
|
+
https://egeria-project.org/types/
|
1129
|
+
|
1130
|
+
Parameters
|
1131
|
+
----------
|
1132
|
+
element_guid: str
|
1133
|
+
- the base element to get related elements for
|
1134
|
+
relationship_type: str
|
1135
|
+
- the type of relationship to navigate to related elements
|
1136
|
+
property_value: str
|
1137
|
+
- property value to be searched.
|
1138
|
+
property_names: [str]
|
1139
|
+
- property names to search in.
|
1140
|
+
metadata_element_type_name : str, default = None
|
1141
|
+
- restrict search to elements of this open metadata type
|
1142
|
+
start_at_end: int, default = 1
|
1143
|
+
- The end of the relationship to start from - typically End1
|
1144
|
+
- open metadata type to be used to restrict the search
|
1145
|
+
effective_time: str, default = None
|
1146
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
1147
|
+
for_lineage: bool, default is set by server
|
1148
|
+
- determines if elements classified as Memento should be returned - normally false
|
1149
|
+
for_duplicate_processing: bool, default is set by server
|
1150
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
1151
|
+
start_from: int, default = 0
|
1152
|
+
- index of the list to start from (0 for start).
|
1153
|
+
page_size
|
1154
|
+
- maximum number of elements to return.
|
1155
|
+
|
1156
|
+
|
1157
|
+
time_out: int, default = default_time_out
|
1158
|
+
- http request timeout for this request
|
1159
|
+
|
1160
|
+
Returns
|
1161
|
+
-------
|
1162
|
+
[dict] | str
|
1163
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
1164
|
+
|
1165
|
+
Raises
|
1166
|
+
------
|
1167
|
+
PyegeriaException
|
1168
|
+
"""
|
1169
|
+
|
1170
|
+
body = {
|
1171
|
+
"class": "FindPropertyNamesProperties",
|
1172
|
+
"metadataElementTypeName": metadata_element_type_name,
|
1173
|
+
"propertyValue": property_value,
|
1174
|
+
"propertyNames": property_names,
|
1175
|
+
"effectiveTime": effective_time,
|
1176
|
+
"forLineage": for_lineage,
|
1177
|
+
"forDuplicateProcessing": for_duplicate_processing,
|
1178
|
+
"startFrom": start_from,
|
1179
|
+
"pageSize": page_size
|
1180
|
+
}
|
1181
|
+
|
1182
|
+
url = (
|
1183
|
+
f"{self.platform_url}/servers/{self.server_name}/api/open-metadata/classification-explorer/elements/{element_guid}"
|
1184
|
+
f"/by-relationship/{relationship_type}/with-exact-property-value?startAtEnd={start_at_end}"
|
1185
|
+
)
|
1186
|
+
|
1187
|
+
response: Response = await self._async_make_request(
|
1188
|
+
"POST", url, body_slimmer(body), time_out=time_out
|
1189
|
+
)
|
1190
|
+
elements = response.json().get("elements", NO_ELEMENTS_FOUND)
|
1191
|
+
if type(elements) is list:
|
1192
|
+
if len(elements) == 0:
|
1193
|
+
return NO_ELEMENTS_FOUND
|
1194
|
+
return elements
|
1195
|
+
|
1196
|
+
def get_relationships_with_property_value(
|
1197
|
+
self,
|
1198
|
+
relationship_type: str,
|
1199
|
+
property_value: str,
|
1200
|
+
property_names: [str],
|
1201
|
+
effective_time: str = None,
|
1202
|
+
for_lineage: bool = None,
|
1203
|
+
for_duplicate_processing: bool = None,
|
1204
|
+
start_from: int = 0,
|
1205
|
+
page_size: int = max_paging_size,
|
1206
|
+
time_out: int = default_time_out,
|
1207
|
+
) -> list | str:
|
1208
|
+
"""
|
1209
|
+
Retrieve relationships of the requested relationship type name and with the requested a value found in
|
1210
|
+
one of the relationship's properties specified. The value must match exactly.
|
1211
|
+
|
1212
|
+
Parameters
|
1213
|
+
----------
|
1214
|
+
relationship_type: str
|
1215
|
+
- the type of relationship to navigate to related elements
|
1216
|
+
property_value: str
|
1217
|
+
- property value to be searched.
|
1218
|
+
property_names: [str]
|
1219
|
+
- property names to search in.
|
1220
|
+
effective_time: str, default = None
|
1221
|
+
- Time format is "YYYY-MM-DDTHH:MM:SS" (ISO 8601)
|
1222
|
+
for_lineage: bool, default is set by server
|
1223
|
+
- determines if elements classified as Memento should be returned - normally false
|
1224
|
+
for_duplicate_processing: bool, default is set by server
|
1225
|
+
- Normally false. Set true when the caller is part of a deduplication function
|
1226
|
+
start_from: int, default = 0
|
1227
|
+
- index of the list to start from (0 for start).
|
1228
|
+
page_size
|
1229
|
+
- maximum number of elements to return.
|
1230
|
+
|
1231
|
+
|
1232
|
+
time_out: int, default = default_time_out
|
1233
|
+
- http request timeout for this request
|
1234
|
+
|
1235
|
+
Returns
|
1236
|
+
-------
|
1237
|
+
[dict] | str
|
1238
|
+
Returns a string if no elements found and a list of dict of elements with the results.
|
1239
|
+
|
1240
|
+
Raises
|
1241
|
+
------
|
1242
|
+
InvalidParameterException
|
1243
|
+
one of the parameters is null or invalid or
|
1244
|
+
PropertyServerException
|
1245
|
+
There is a problem adding the element properties to the metadata repository or
|
1246
|
+
UserNotAuthorizedException
|
1247
|
+
the requesting user is not authorized to issue this request.
|
1248
|
+
"""
|
1249
|
+
|
1250
|
+
loop = asyncio.get_event_loop()
|
1251
|
+
response = loop.run_until_complete(
|
1252
|
+
self._async_get_relationships_with_property_value(
|
1253
|
+
relationship_type,
|
1254
|
+
property_value,
|
1255
|
+
property_names,
|
1256
|
+
effective_time,
|
1257
|
+
for_lineage,
|
1258
|
+
for_duplicate_processing,
|
1259
|
+
start_from,
|
1260
|
+
page_size,
|
1261
|
+
time_out,
|
1262
|
+
)
|
1263
|
+
)
|
1264
|
+
return response
|
1265
|
+
|
1266
|
+
async def async_get_connector_guid(self, connector_name: str) -> str:
|
1267
|
+
"""Get the guid of a connector. Async version.
|
1268
|
+
Parameters:
|
1269
|
+
connector_name (str): The name of the connector to retrieve the guid for.
|
1270
|
+
Returns:
|
1271
|
+
str: The guid of the connector.
|
1272
|
+
"""
|
1273
|
+
rel = await self._async_get_relationships_with_property_value(relationship_type="RegisteredIntegrationConnector",
|
1274
|
+
property_names=["connectorName"],
|
1275
|
+
property_value=connector_name,
|
1276
|
+
)
|
1277
|
+
if rel == "No elements found":
|
1278
|
+
logger.error(f"\n\n===> No connector found with name '{connector_name}'\n\n")
|
1279
|
+
return "No connector found"
|
1280
|
+
connector_guid = rel[0]['end2']['guid']
|
1281
|
+
|
1282
|
+
if connector_guid is None:
|
1283
|
+
logger.error(f"\n\n===> No connector found with name '{connector_name}'\n\n")
|
1284
|
+
return "No connector found"
|
1285
|
+
|
1286
|
+
return connector_guid
|
1287
|
+
|
1288
|
+
|
1289
|
+
def get_connector_guid(self, connector_name: str) -> str:
|
1290
|
+
"""Get the guid of a connector.
|
1291
|
+
Parameters:
|
1292
|
+
connector_name (str): The name of the connector to retrieve the guid for.
|
1293
|
+
Returns:
|
1294
|
+
str: The guid of the connector.
|
1295
|
+
"""
|
1296
|
+
|
1297
|
+
loop = asyncio.get_event_loop()
|
1298
|
+
result = loop.run_until_complete(
|
1299
|
+
self.async_get_connector_guid(
|
1300
|
+
connector_name
|
1301
|
+
)
|
1302
|
+
)
|
1303
|
+
return result
|
1304
|
+
|
1305
|
+
|
1306
|
+
|
1307
|
+
#
|
1308
|
+
# Helper functions for requests
|
1309
|
+
#
|
1310
|
+
|
1311
|
+
|
776
1312
|
def validate_new_element_request(self, body: dict | NewElementRequestBody,
|
777
1313
|
prop: list[str]) -> NewElementRequestBody | None:
|
778
1314
|
if isinstance(body, NewElementRequestBody):
|
@@ -1029,7 +1565,7 @@ class Client2:
|
|
1029
1565
|
json_body = validated_body.model_dump_json(indent=2, exclude_none=True)
|
1030
1566
|
|
1031
1567
|
response = await self._async_make_request("POST", url, json_body)
|
1032
|
-
elements = response.json().get("
|
1568
|
+
elements = response.json().get("element", NO_ELEMENTS_FOUND)
|
1033
1569
|
if type(elements) is str:
|
1034
1570
|
logger.info(NO_ELEMENTS_FOUND)
|
1035
1571
|
return NO_ELEMENTS_FOUND
|
@@ -1101,6 +1637,35 @@ class Client2:
|
|
1101
1637
|
output_format, output_format_set)
|
1102
1638
|
return elements
|
1103
1639
|
|
1640
|
+
async def _async_get_level_identifier_query_body_request(self, url: str, _gen_output: Callable[..., Any],
|
1641
|
+
output_format: str = 'JSON',
|
1642
|
+
output_format_set: str | dict = None,
|
1643
|
+
body: dict | ResultsRequestBody = None) -> Any:
|
1644
|
+
if isinstance(body, LevelIdentifierQueryBody):
|
1645
|
+
validated_body = body
|
1646
|
+
elif isinstance(body, dict):
|
1647
|
+
validated_body = self._level_identifier_query_body.validate_python(body)
|
1648
|
+
else:
|
1649
|
+
return None
|
1650
|
+
|
1651
|
+
json_body = validated_body.model_dump_json(indent=2, exclude_none=True)
|
1652
|
+
|
1653
|
+
response = await self._async_make_request("POST", url, json_body)
|
1654
|
+
elements = response.json().get("elements", None)
|
1655
|
+
if elements is None:
|
1656
|
+
elements = response.json().get("element", NO_ELEMENTS_FOUND)
|
1657
|
+
|
1658
|
+
if type(elements) is str:
|
1659
|
+
logger.info(NO_ELEMENTS_FOUND)
|
1660
|
+
return NO_ELEMENTS_FOUND
|
1661
|
+
|
1662
|
+
if output_format != 'JSON': # return a simplified markdown representation
|
1663
|
+
logger.info(f"Found elements, output format: {output_format} and output_format_set: {output_format_set}")
|
1664
|
+
return _gen_output(elements, "", "Referenceable",
|
1665
|
+
output_format, output_format_set)
|
1666
|
+
return elements
|
1667
|
+
|
1668
|
+
|
1104
1669
|
async def _async_create_element_body_request(self, url: str, prop: list[str],
|
1105
1670
|
body: dict | NewElementRequestBody = None) -> str:
|
1106
1671
|
validated_body = self.validate_new_element_request(body, prop)
|
@@ -1633,4 +2198,33 @@ class Client2:
|
|
1633
2198
|
# }
|
1634
2199
|
# """
|
1635
2200
|
# loop = asyncio.get_event_loop()
|
1636
|
-
# loop.run_until_complete(self._async_update_element_status(guid, status, body))
|
2201
|
+
# loop.run_until_complete(self._async_update_element_status(guid, status, body))
|
2202
|
+
|
2203
|
+
@dynamic_catch
|
2204
|
+
def _extract_referenceable_properties(self, element: dict, columns_struct: dict) -> dict:
|
2205
|
+
"""Populate default Referenceable columns for output using common population pipeline."""
|
2206
|
+
return populate_common_columns(element, columns_struct)
|
2207
|
+
|
2208
|
+
@dynamic_catch
|
2209
|
+
def _generate_referenceable_output(self, elements: dict | list[dict], search_string: str | None,
|
2210
|
+
element_type_name: str | None,
|
2211
|
+
output_format: str = "JSON",
|
2212
|
+
output_format_set: dict | str = None) -> str | list[dict]:
|
2213
|
+
"""Generate formatted output for generic Referenceable elements.
|
2214
|
+
|
2215
|
+
If output_format is 'JSON', returns elements unchanged. Otherwise, resolves an
|
2216
|
+
output format set and delegates to generate_output with a standard extractor.
|
2217
|
+
"""
|
2218
|
+
if output_format == "JSON":
|
2219
|
+
return elements
|
2220
|
+
entity_type = element_type_name or "Referenceable"
|
2221
|
+
output_formats = resolve_output_formats(entity_type, output_format, output_format_set, default_label=entity_type)
|
2222
|
+
return generate_output(
|
2223
|
+
elements=elements,
|
2224
|
+
search_string=search_string,
|
2225
|
+
entity_type=entity_type,
|
2226
|
+
output_format=output_format,
|
2227
|
+
extract_properties_func=self._extract_referenceable_properties,
|
2228
|
+
get_additional_props_func=None,
|
2229
|
+
columns_struct=output_formats,
|
2230
|
+
)
|