pyegeria 5.4.0.26__py3-none-any.whl → 5.4.0.28__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/debug_log +868 -7794
- commands/cat/debug_log.2025-08-18_11-34-38_088636.zip +0 -0
- commands/cat/list_collections.py +1 -1
- commands/cat/list_format_set.py +6 -8
- commands/cli/egeria.py +2 -2
- commands/cli/egeria_cat.py +3 -2
- commands/ops/load_archive.py +2 -2
- md_processing/data/commands.json +7 -7
- md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +7 -7
- md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +36 -31
- md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:22-dr_egeria_intro_part1.md +312 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:23-dr_egeria_intro_part1.md +265 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:06-dr_egeria_intro_part1.md +230 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:30-dr_egeria_intro_part1.md +296 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:31-dr_egeria_intro_part1.md +253 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:08-dr_egeria_intro_part2.md +343 -0
- md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:12-dr_egeria_intro_part2.md +343 -0
- md_processing/md_commands/glossary_commands.py +888 -951
- md_processing/md_commands/product_manager_commands.py +8 -270
- md_processing/md_commands/project_commands.py +1 -1
- md_processing/md_processing_utils/common_md_proc_utils.py +138 -64
- md_processing/md_processing_utils/common_md_utils.py +2 -1
- pyegeria/__init__.py +2 -3
- pyegeria/_client_new.py +4 -3
- pyegeria/_output_formats.py +5 -3
- pyegeria/collection_manager.py +32 -29
- pyegeria/{load_config.py → config.py} +7 -2
- pyegeria/data_designer.py +154 -194
- pyegeria/egeria_cat_client.py +46 -28
- pyegeria/egeria_client.py +71 -72
- pyegeria/egeria_config_client.py +37 -7
- pyegeria/egeria_my_client.py +45 -10
- pyegeria/egeria_tech_client.py +68 -57
- pyegeria/glossary_manager.py +495 -124
- pyegeria/governance_officer.py +2 -2
- pyegeria/logging_configuration.py +1 -4
- pyegeria/models.py +1 -1
- pyegeria/project_manager.py +359 -511
- pyegeria/utils.py +1 -3
- {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.28.dist-info}/METADATA +1 -1
- {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.28.dist-info}/RECORD +44 -38
- md_processing/md_processing_utils/solution_architect_log.log +0 -0
- pyegeria/glossary_browser.py +0 -1259
- {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.28.dist-info}/LICENSE +0 -0
- {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.28.dist-info}/WHEEL +0 -0
- {pyegeria-5.4.0.26.dist-info → pyegeria-5.4.0.28.dist-info}/entry_points.txt +0 -0
pyegeria/glossary_manager.py
CHANGED
@@ -21,14 +21,18 @@ from pyegeria._exceptions import InvalidParameterException
|
|
21
21
|
from pyegeria._exceptions_new import PyegeriaInvalidParameterException
|
22
22
|
from pyegeria._globals import NO_GUID_RETURNED
|
23
23
|
from pyegeria._validators import validate_guid
|
24
|
-
from pyegeria.
|
25
|
-
from pyegeria.
|
24
|
+
from pyegeria.collection_manager import CollectionManager
|
25
|
+
from pyegeria.config import settings as app_settings
|
26
26
|
from pyegeria.models import (NewElementRequestBody,
|
27
27
|
ReferenceableProperties, UpdateElementRequestBody, DeleteRequestBody, TemplateRequestBody,
|
28
|
-
NewRelationshipRequestBody, UpdateRelationshipRequestBody, NewClassificationRequestBody
|
29
|
-
|
28
|
+
NewRelationshipRequestBody, UpdateRelationshipRequestBody, NewClassificationRequestBody,
|
29
|
+
FilterRequestBody, GetRequestBody, SearchStringRequestBody, UpdateStatusRequestBody)
|
30
|
+
from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
|
31
|
+
from pyegeria.output_formatter import (generate_output,
|
32
|
+
_extract_referenceable_properties, populate_columns_from_properties,
|
33
|
+
get_required_relationships)
|
34
|
+
from pyegeria.utils import body_slimmer, dynamic_catch
|
30
35
|
|
31
|
-
app_settings = get_app_config()
|
32
36
|
EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
|
33
37
|
|
34
38
|
|
@@ -72,7 +76,7 @@ class GlossaryTermProperties(ReferenceableProperties):
|
|
72
76
|
publishVersionIdentifier: str = None
|
73
77
|
|
74
78
|
|
75
|
-
class GlossaryManager(
|
79
|
+
class GlossaryManager(CollectionManager):
|
76
80
|
"""
|
77
81
|
GlossaryManager is a class that extends the Client class. It provides methods to create and manage glossaries,
|
78
82
|
terms and categories.
|
@@ -106,7 +110,7 @@ class GlossaryManager(GlossaryBrowser):
|
|
106
110
|
self.user_id = user_id
|
107
111
|
self.user_pwd = user_pwd
|
108
112
|
|
109
|
-
|
113
|
+
CollectionManager.__init__(self, view_server, platform_url, user_id, user_pwd, token)
|
110
114
|
|
111
115
|
#
|
112
116
|
# Get Valid Values for Enumerations
|
@@ -121,108 +125,37 @@ class GlossaryManager(GlossaryBrowser):
|
|
121
125
|
# Glossaries
|
122
126
|
#
|
123
127
|
|
124
|
-
async def _async_create_glossary(
|
125
|
-
self,
|
126
|
-
display_name: str,
|
127
|
-
description: str,
|
128
|
-
language: str = "English",
|
129
|
-
usage: str = None,
|
130
|
-
initial_classifications: list = None,
|
131
|
-
body: dict | NewElementRequestBody = None,
|
132
|
-
) -> str:
|
133
|
-
"""Create a new glossary. Async version.
|
134
|
-
|
135
|
-
Parameters
|
136
|
-
----------
|
137
|
-
display_name: str
|
138
|
-
The name of the new glossary. This will be used to produce a unique qualified name for the glossary.
|
139
|
-
description: str
|
140
|
-
A description of the glossary.
|
141
|
-
language: str, optional, default = "English"
|
142
|
-
The language the used for the glossary
|
143
|
-
usage: str, optional, default = None
|
144
|
-
How the glossary is intended to be used
|
145
128
|
|
146
129
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries"
|
155
|
-
if body:
|
156
|
-
validated_body = self.validate_new_element_request(body, "GlossaryProperties")
|
157
|
-
elif (body is None) and (display_name is not None):
|
158
|
-
pre = initial_classifications[0] if initial_classifications is not None else "Glossary"
|
159
|
-
qualified_name = self.__create_qualified_name__(pre, display_name, EGERIA_LOCAL_QUALIFIER)
|
160
|
-
if initial_classifications:
|
161
|
-
initial_classifications_dict = {}
|
162
|
-
for c in initial_classifications:
|
163
|
-
initial_classifications_dict = initial_classifications_dict | {
|
164
|
-
c: {"class": "ClassificationProperties"}
|
165
|
-
}
|
166
|
-
|
167
|
-
else:
|
168
|
-
initial_classifications_dict = None
|
169
|
-
|
170
|
-
glossary_properties = GlossaryProperties(class_="GlossaryProperties",
|
171
|
-
qualified_name=qualified_name,
|
172
|
-
display_name=display_name,
|
173
|
-
description=description,
|
174
|
-
language=language,
|
175
|
-
usage=usage
|
176
|
-
)
|
130
|
+
@dynamic_catch
|
131
|
+
async def _async_create_glossary(self, display_name: str, description: str = None, language: str = "English", usage: str = None,
|
132
|
+
category: str = None, body: dict | NewElementRequestBody = None) -> str:
|
133
|
+
"""Create a new glossary with optional classification. """
|
134
|
+
if body is None:
|
135
|
+
qualified_name = self.__create_qualified_name__("Glossary", display_name, EGERIA_LOCAL_QUALIFIER)
|
177
136
|
body = {
|
178
137
|
"class": "NewElementRequestBody",
|
179
|
-
"
|
180
|
-
"
|
181
|
-
|
138
|
+
"is_own_anchor": True,
|
139
|
+
"properties": {
|
140
|
+
"class": "GlossaryProperties",
|
141
|
+
"displayName": display_name,
|
142
|
+
"qualifiedName": qualified_name,
|
143
|
+
"description": description,
|
144
|
+
"language": language,
|
145
|
+
"usage": usage,
|
146
|
+
"category": category
|
147
|
+
},
|
182
148
|
}
|
183
|
-
|
184
|
-
|
185
|
-
raise PyegeriaInvalidParameterException(additional_info={"reason": "Invalid input parameters"})
|
186
|
-
|
187
|
-
json_body = validated_body.model_dump_json(indent=2, exclude_none=True)
|
188
|
-
logger.info(json_body)
|
189
|
-
resp = await self._async_make_request("POST", url, json_body, is_json=True)
|
190
|
-
logger.info(f"Create glossary with GUID: {resp.json().get('guid')}")
|
191
|
-
return resp.json().get("guid", NO_GUID_RETURNED)
|
192
|
-
|
193
|
-
def create_glossary(
|
194
|
-
self,
|
195
|
-
display_name: str,
|
196
|
-
description: str,
|
197
|
-
language: str = "English",
|
198
|
-
usage: str = None,
|
199
|
-
initial_classifications: list = None,
|
200
|
-
body: dict | NewElementRequestBody = None
|
201
|
-
) -> str:
|
202
|
-
"""Create a new glossary.
|
203
|
-
|
204
|
-
Parameters
|
205
|
-
----------
|
206
|
-
display_name: str
|
207
|
-
The name of the new glossary. This will be used to produce a unique qualified name for the glossary.
|
208
|
-
description: str
|
209
|
-
A description of the glossary.
|
210
|
-
language: str, optional, default = "English"
|
211
|
-
The language the used for the glossary
|
212
|
-
usage: str, optional, default = None
|
213
|
-
How the glossary is intended to be used
|
214
|
-
|
215
|
-
|
216
|
-
Returns
|
217
|
-
-------
|
218
|
-
str
|
219
|
-
The GUID of the created glossary.
|
149
|
+
response = await self._async_create_collection(body=body)
|
150
|
+
return response
|
220
151
|
|
221
|
-
|
152
|
+
def create_glossary(self, display_name: str, description: str = None, language: str = "English",
|
153
|
+
usage: str = None,
|
154
|
+
category: str = None, body: dict | NewElementRequestBody = None) -> str:
|
155
|
+
"""Create a new glossary with optional classification. """
|
222
156
|
loop = asyncio.get_event_loop()
|
223
157
|
response = loop.run_until_complete(
|
224
|
-
self._async_create_glossary(display_name, description, language, usage,
|
225
|
-
initial_classifications, body)
|
158
|
+
self._async_create_glossary(display_name, description, language, usage, category, body)
|
226
159
|
)
|
227
160
|
return response
|
228
161
|
|
@@ -243,13 +176,9 @@ class GlossaryManager(GlossaryBrowser):
|
|
243
176
|
|
244
177
|
"""
|
245
178
|
|
246
|
-
|
247
|
-
f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
|
248
|
-
f"{glossary_guid}/delete"
|
249
|
-
)
|
179
|
+
await self._async_delete_collection(glossary_guid, body, cascade)
|
250
180
|
|
251
|
-
|
252
|
-
logger.info(f"Deleted collection {glossary_guid} with cascade {cascade}")
|
181
|
+
logger.info(f"Deleted glossary {glossary_guid} with cascade {cascade}")
|
253
182
|
|
254
183
|
def delete_glossary(self, glossary_guid: str, body: dict | DeleteRequestBody = None, cascade: bool = False) -> None:
|
255
184
|
"""Delete a new glossary.
|
@@ -273,7 +202,8 @@ class GlossaryManager(GlossaryBrowser):
|
|
273
202
|
async def _async_update_glossary(
|
274
203
|
self,
|
275
204
|
glossary_guid: str,
|
276
|
-
body: dict | UpdateElementRequestBody
|
205
|
+
body: dict | UpdateElementRequestBody,
|
206
|
+
merge_update: bool = True,
|
277
207
|
) -> None:
|
278
208
|
"""Update Glossary.
|
279
209
|
|
@@ -297,18 +227,16 @@ class GlossaryManager(GlossaryBrowser):
|
|
297
227
|
|
298
228
|
"""
|
299
229
|
|
300
|
-
url = (
|
301
|
-
f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
|
302
|
-
f"{glossary_guid}/update"
|
303
|
-
)
|
304
230
|
|
305
|
-
|
231
|
+
|
232
|
+
await self._async_update_collection(glossary_guid, body, is_merge_update=merge_update)
|
306
233
|
logger.info(f"Updated digital subscription {glossary_guid}")
|
307
234
|
|
308
235
|
def update_glossary(
|
309
236
|
self,
|
310
237
|
glossary_guid: str,
|
311
|
-
body: dict | UpdateElementRequestBody
|
238
|
+
body: dict | UpdateElementRequestBody,
|
239
|
+
merge_update: bool = True,
|
312
240
|
) -> None:
|
313
241
|
"""Update Glossary.
|
314
242
|
|
@@ -321,10 +249,6 @@ class GlossaryManager(GlossaryBrowser):
|
|
321
249
|
is_merge_update: bool, optional, default = True
|
322
250
|
If true, then only those properties specified in the body will be updated. If false, then all the
|
323
251
|
properties of the glossary will be replaced with those of the body.
|
324
|
-
for_lineage: bool, optional, default = False
|
325
|
-
Normally false. Used when we want to retrieve elements that have been delete but have a Memento entry.
|
326
|
-
for_duplicate_processing: bool, optional, default = False
|
327
|
-
Normally false. Set true when Egeria is told to skip deduplication because another system will do it.
|
328
252
|
|
329
253
|
|
330
254
|
Returns
|
@@ -342,7 +266,7 @@ class GlossaryManager(GlossaryBrowser):
|
|
342
266
|
loop.run_until_complete(
|
343
267
|
self._async_update_glossary(
|
344
268
|
glossary_guid,
|
345
|
-
body
|
269
|
+
body, merge_update
|
346
270
|
)
|
347
271
|
)
|
348
272
|
|
@@ -983,7 +907,7 @@ class GlossaryManager(GlossaryBrowser):
|
|
983
907
|
|
984
908
|
return response
|
985
909
|
|
986
|
-
async def
|
910
|
+
async def _async_update_glossary_term(
|
987
911
|
self,
|
988
912
|
glossary_term_guid: str,
|
989
913
|
body: dict | UpdateElementRequestBody,
|
@@ -1025,7 +949,7 @@ class GlossaryManager(GlossaryBrowser):
|
|
1025
949
|
await self._async_update_element_body_request(url, ["GlossaryTermProperties"], body)
|
1026
950
|
logger.info(f"Updated digital subscription {glossary_term_guid}")
|
1027
951
|
|
1028
|
-
def
|
952
|
+
def update_glossary_term(
|
1029
953
|
self,
|
1030
954
|
glossary_term_guid: str,
|
1031
955
|
body: dict | UpdateElementRequestBody,
|
@@ -1074,13 +998,102 @@ class GlossaryManager(GlossaryBrowser):
|
|
1074
998
|
"""
|
1075
999
|
loop = asyncio.get_event_loop()
|
1076
1000
|
loop.run_until_complete(
|
1077
|
-
self.
|
1001
|
+
self._async_update_glossary_term(
|
1078
1002
|
glossary_term_guid,
|
1079
1003
|
body,
|
1080
1004
|
)
|
1081
1005
|
)
|
1082
1006
|
|
1083
1007
|
|
1008
|
+
@dynamic_catch
|
1009
|
+
async def _async_update_term_status(self, term_guid: str, status: str = None,
|
1010
|
+
body: dict | UpdateStatusRequestBody = None):
|
1011
|
+
"""Update the status of a collection. Async version.
|
1012
|
+
|
1013
|
+
Parameters
|
1014
|
+
----------
|
1015
|
+
collection_guid: str
|
1016
|
+
The guid of the collection to update.
|
1017
|
+
status: str, optional
|
1018
|
+
The new lifecycle status for the collection. Ignored, if the body is provided.
|
1019
|
+
body: dict | UpdateStatusRequestBody, optional
|
1020
|
+
A structure representing the details of the collection to create. If supplied, these details
|
1021
|
+
supersede the status parameter provided.
|
1022
|
+
|
1023
|
+
Returns
|
1024
|
+
-------
|
1025
|
+
Nothing
|
1026
|
+
|
1027
|
+
Raises
|
1028
|
+
------
|
1029
|
+
InvalidParameterException
|
1030
|
+
If the client passes incorrect parameters on the request - such as bad URLs or invalid values
|
1031
|
+
PropertyServerException
|
1032
|
+
Raised by the server when an issue arises in processing a valid request
|
1033
|
+
NotAuthorizedException
|
1034
|
+
The principle specified by the user_id does not have authorization for the requested action
|
1035
|
+
|
1036
|
+
Notes
|
1037
|
+
-----
|
1038
|
+
JSON Structure looks like:
|
1039
|
+
{
|
1040
|
+
"class": "UpdateStatusRequestBody",
|
1041
|
+
"status": "APPROVED",
|
1042
|
+
"externalSourceGUID": "add guid here",
|
1043
|
+
"externalSourceName": "add qualified name here",
|
1044
|
+
"effectiveTime": "{{$isoTimestamp}}",
|
1045
|
+
"forLineage": false,
|
1046
|
+
"forDuplicateProcessing": false
|
1047
|
+
}
|
1048
|
+
"""
|
1049
|
+
|
1050
|
+
url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/metadata-elements/{term_guid}/update-status"
|
1051
|
+
await self._async_update_status_request(url, status, body)
|
1052
|
+
logger.info(f"Updated status for term {term_guid}")
|
1053
|
+
|
1054
|
+
@dynamic_catch
|
1055
|
+
def update_term_status(self, term_guid: str, status: str = None,
|
1056
|
+
body: dict | UpdateStatusRequestBody = None):
|
1057
|
+
"""Update the status of a DigitalProduct collection.
|
1058
|
+
|
1059
|
+
Parameters
|
1060
|
+
----------
|
1061
|
+
collection_guid: str
|
1062
|
+
The guid of the collection to update.
|
1063
|
+
status: str, optional
|
1064
|
+
The new lifecycle status for the digital product. Ignored, if the body is provided.
|
1065
|
+
body: dict | UpdateStatusRequestBody, optional
|
1066
|
+
A structure representing the details of the collection to create. If supplied, these details
|
1067
|
+
supersede the status parameter provided.
|
1068
|
+
|
1069
|
+
Returns
|
1070
|
+
-------
|
1071
|
+
Nothing
|
1072
|
+
|
1073
|
+
Raises
|
1074
|
+
------
|
1075
|
+
InvalidParameterException
|
1076
|
+
If the client passes incorrect parameters on the request - such as bad URLs or invalid values
|
1077
|
+
PropertyServerException
|
1078
|
+
Raised by the server when an issue arises in processing a valid request
|
1079
|
+
NotAuthorizedException
|
1080
|
+
The principle specified by the user_id does not have authorization for the requested action
|
1081
|
+
|
1082
|
+
Notes
|
1083
|
+
-----
|
1084
|
+
JSON Structure looks like:
|
1085
|
+
{
|
1086
|
+
"class": "UpdateStatusRequestBody",
|
1087
|
+
"status": "APPROVED",
|
1088
|
+
"externalSourceGUID": "add guid here",
|
1089
|
+
"externalSourceName": "add qualified name here",
|
1090
|
+
"effectiveTime": "{{$isoTimestamp}}",
|
1091
|
+
"forLineage": false,
|
1092
|
+
"forDuplicateProcessing": false
|
1093
|
+
}
|
1094
|
+
"""
|
1095
|
+
loop = asyncio.get_event_loop()
|
1096
|
+
loop.run_until_complete(self._async_update_collection_status(term_guid, status, body))
|
1084
1097
|
|
1085
1098
|
|
1086
1099
|
async def _async_delete_term(
|
@@ -1240,9 +1253,18 @@ class GlossaryManager(GlossaryBrowser):
|
|
1240
1253
|
|
1241
1254
|
|
1242
1255
|
#
|
1243
|
-
#
|
1256
|
+
# Categories are just Folders in collection manager
|
1257
|
+
#
|
1258
|
+
|
1259
|
+
|
1260
|
+
#
|
1261
|
+
# From glossary browser
|
1244
1262
|
#
|
1245
1263
|
|
1264
|
+
|
1265
|
+
|
1266
|
+
|
1267
|
+
|
1246
1268
|
async def _async_add_is_abstract_concepts(
|
1247
1269
|
self, term_guid: str, body: dict | NewClassificationRequestBody = None,
|
1248
1270
|
) -> None:
|
@@ -1308,7 +1330,6 @@ class GlossaryManager(GlossaryBrowser):
|
|
1308
1330
|
logger.info(f"Added AbstractConcept classification to {term_guid}")
|
1309
1331
|
|
1310
1332
|
|
1311
|
-
|
1312
1333
|
def add_is_abstract_concept(
|
1313
1334
|
self, term_guid: str, body: dict | NewClassificationRequestBody = None,
|
1314
1335
|
) -> None:
|
@@ -2517,6 +2538,356 @@ class GlossaryManager(GlossaryBrowser):
|
|
2517
2538
|
body)
|
2518
2539
|
)
|
2519
2540
|
|
2541
|
+
#
|
2542
|
+
# Integrated Glossary Browser methods
|
2543
|
+
#
|
2544
|
+
|
2545
|
+
def _extract_glossary_properties(self, element: dict, columns_struct: dict) -> dict:
|
2546
|
+
props = element.get('properties', {}) or {}
|
2547
|
+
normalized = {
|
2548
|
+
'properties': props,
|
2549
|
+
'elementHeader': element.get('elementHeader', {}),
|
2550
|
+
}
|
2551
|
+
col_data = populate_columns_from_properties(normalized, columns_struct)
|
2552
|
+
columns_list = col_data.get('formats', {}).get('columns', [])
|
2553
|
+
header_props = _extract_referenceable_properties(element)
|
2554
|
+
guid = header_props.get('GUID')
|
2555
|
+
for column in columns_list:
|
2556
|
+
key = column.get('key')
|
2557
|
+
if key in header_props:
|
2558
|
+
column['value'] = header_props.get(key)
|
2559
|
+
elif isinstance(key, str) and key.lower() == 'guid':
|
2560
|
+
column['value'] = guid
|
2561
|
+
if guid:
|
2562
|
+
categories = None
|
2563
|
+
try:
|
2564
|
+
categories = self.get_categories_for_glossary(guid)
|
2565
|
+
except Exception:
|
2566
|
+
categories = None
|
2567
|
+
cat_display_list = []
|
2568
|
+
cat_qn_list = []
|
2569
|
+
if isinstance(categories, list):
|
2570
|
+
for category in categories:
|
2571
|
+
gcp = category.get('glossaryCategoryProperties', {})
|
2572
|
+
dn = gcp.get('displayName', '') or ''
|
2573
|
+
qn = gcp.get('qualifiedName', '') or ''
|
2574
|
+
if dn:
|
2575
|
+
cat_display_list.append(dn)
|
2576
|
+
if qn:
|
2577
|
+
cat_qn_list.append(qn)
|
2578
|
+
cat_names_md = (", \n".join(cat_display_list)).rstrip(',') if cat_display_list else ''
|
2579
|
+
cat_qn_md = (", \n".join(cat_qn_list)).rstrip(',') if cat_qn_list else ''
|
2580
|
+
for column in columns_list:
|
2581
|
+
if column.get('key') == 'categories_names' and not column.get('value'):
|
2582
|
+
column['value'] = cat_names_md
|
2583
|
+
if column.get('key') == 'categories_qualified_names' and not column.get('value'):
|
2584
|
+
column['value'] = cat_qn_md
|
2585
|
+
for column in columns_list:
|
2586
|
+
if column.get('key') == 'mermaid' and not column.get('value'):
|
2587
|
+
column['value'] = element.get('mermaidGraph', '') or ''
|
2588
|
+
break
|
2589
|
+
return col_data
|
2590
|
+
|
2591
|
+
def _extract_term_properties(self, element: dict, columns_struct: dict) -> dict:
|
2592
|
+
col_data = populate_columns_from_properties(element, columns_struct)
|
2593
|
+
columns_list = col_data.get("formats", {}).get("columns", [])
|
2594
|
+
header_props = _extract_referenceable_properties(element)
|
2595
|
+
for column in columns_list:
|
2596
|
+
key = column.get('key')
|
2597
|
+
if key in header_props:
|
2598
|
+
column['value'] = header_props.get(key)
|
2599
|
+
elif isinstance(key, str) and key.lower() == 'guid':
|
2600
|
+
column['value'] = header_props.get('GUID')
|
2601
|
+
classification_names = ""
|
2602
|
+
classifications = element.get('elementHeader', {}).get("collectionCategories", [])
|
2603
|
+
for classification in classifications:
|
2604
|
+
classification_names += f"{classification['classificationName']}, "
|
2605
|
+
if classification_names:
|
2606
|
+
for column in columns_list:
|
2607
|
+
if column.get('key') == 'classifications':
|
2608
|
+
column['value'] = classification_names[:-2]
|
2609
|
+
break
|
2610
|
+
col_data = get_required_relationships(element, col_data)
|
2611
|
+
subject_area = element.get('elementHeader', {}).get("subjectArea", "") or ""
|
2612
|
+
subj_val = ""
|
2613
|
+
if isinstance(subject_area, dict):
|
2614
|
+
subj_val = subject_area.get("classificationProperties", {}).get("subjectAreaName", "")
|
2615
|
+
for column in columns_list:
|
2616
|
+
if column.get('key') == 'subject_area':
|
2617
|
+
column['value'] = subj_val
|
2618
|
+
break
|
2619
|
+
mermaid_val = element.get('mermaidGraph', "") or ""
|
2620
|
+
for column in columns_list:
|
2621
|
+
if column.get('key') == 'mermaid':
|
2622
|
+
column['value'] = mermaid_val
|
2623
|
+
break
|
2624
|
+
return col_data
|
2625
|
+
|
2626
|
+
def _get_term_additional_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
|
2627
|
+
additional: dict = {}
|
2628
|
+
try:
|
2629
|
+
classifications = element.get('elementHeader', {}).get('otherClassifications', [])
|
2630
|
+
glossary_name = ''
|
2631
|
+
if classifications:
|
2632
|
+
cls_props = classifications[0].get('classificationProperties', {}) or {}
|
2633
|
+
g_guid = cls_props.get('anchorScopeGUID')
|
2634
|
+
if g_guid and hasattr(self, 'get_glossary_by_guid'):
|
2635
|
+
try:
|
2636
|
+
gl = self.get_glossary_by_guid(g_guid)
|
2637
|
+
if isinstance(gl, dict):
|
2638
|
+
if output_format == 'REPORT':
|
2639
|
+
glossary_name = gl.get('glossaryProperties', {}).get('displayName', '')
|
2640
|
+
else:
|
2641
|
+
glossary_name = gl.get('glossaryProperties', {}).get('qualifiedName', '')
|
2642
|
+
except Exception:
|
2643
|
+
pass
|
2644
|
+
if glossary_name:
|
2645
|
+
additional['in_glossary'] = glossary_name
|
2646
|
+
except Exception:
|
2647
|
+
pass
|
2648
|
+
try:
|
2649
|
+
if hasattr(self, 'get_categories_for_term') and term_guid:
|
2650
|
+
cats = self.get_categories_for_term(term_guid)
|
2651
|
+
names = []
|
2652
|
+
if isinstance(cats, list):
|
2653
|
+
for c in cats:
|
2654
|
+
gcp = c.get('glossaryCategoryProperties', {})
|
2655
|
+
val = gcp.get('displayName') if output_format in ['REPORT', 'LIST'] else gcp.get('qualifiedName')
|
2656
|
+
if val:
|
2657
|
+
names.append(val)
|
2658
|
+
if names:
|
2659
|
+
additional['categories'] = ", \n".join(names)
|
2660
|
+
except Exception:
|
2661
|
+
pass
|
2662
|
+
return additional
|
2663
|
+
|
2664
|
+
def _generate_glossary_output(self, elements: dict | list[dict], search_string: str,
|
2665
|
+
element_type_name: str | None,
|
2666
|
+
output_format: str = 'DICT',
|
2667
|
+
output_format_set: dict | str = None) -> str | list[dict]:
|
2668
|
+
entity_type = 'Glossary'
|
2669
|
+
if output_format_set:
|
2670
|
+
if isinstance(output_format_set, str):
|
2671
|
+
output_formats = select_output_format_set(output_format_set, output_format)
|
2672
|
+
elif isinstance(output_format_set, dict):
|
2673
|
+
output_formats = get_output_format_type_match(output_format_set, output_format)
|
2674
|
+
else:
|
2675
|
+
output_formats = None
|
2676
|
+
else:
|
2677
|
+
output_formats = select_output_format_set(entity_type, output_format)
|
2678
|
+
if output_formats is None:
|
2679
|
+
output_formats = select_output_format_set('Default', output_format)
|
2680
|
+
return generate_output(
|
2681
|
+
elements=elements,
|
2682
|
+
search_string=search_string,
|
2683
|
+
entity_type=entity_type,
|
2684
|
+
output_format=output_format,
|
2685
|
+
extract_properties_func=self._extract_glossary_properties,
|
2686
|
+
get_additional_props_func=None,
|
2687
|
+
columns_struct=output_formats,
|
2688
|
+
)
|
2689
|
+
|
2690
|
+
def _generate_term_output(self, elements: dict | list[dict], search_string: str,
|
2691
|
+
element_type_name: str | None,
|
2692
|
+
output_format: str = 'DICT',
|
2693
|
+
output_format_set: dict | str = None) -> str | list[dict]:
|
2694
|
+
entity_type = 'GlossaryTerm'
|
2695
|
+
if output_format_set:
|
2696
|
+
if isinstance(output_format_set, str):
|
2697
|
+
output_formats = select_output_format_set(output_format_set, output_format)
|
2698
|
+
elif isinstance(output_format_set, dict):
|
2699
|
+
output_formats = get_output_format_type_match(output_format_set, output_format)
|
2700
|
+
else:
|
2701
|
+
output_formats = None
|
2702
|
+
else:
|
2703
|
+
output_formats = select_output_format_set(entity_type, output_format)
|
2704
|
+
if output_formats is None:
|
2705
|
+
output_formats = select_output_format_set('Default', output_format)
|
2706
|
+
return generate_output(
|
2707
|
+
elements=elements,
|
2708
|
+
search_string=search_string,
|
2709
|
+
entity_type=entity_type,
|
2710
|
+
output_format=output_format,
|
2711
|
+
extract_properties_func=self._extract_term_properties,
|
2712
|
+
get_additional_props_func=self._get_term_additional_properties,
|
2713
|
+
columns_struct=output_formats,
|
2714
|
+
)
|
2715
|
+
|
2716
|
+
async def _async_get_glossary_term_statuses(self) -> [str]:
|
2717
|
+
url = (f"{self.platform_url}/servers/{self.view_server}"
|
2718
|
+
f"/api/open-metadata/glossary-manager/glossaries/terms/status-list")
|
2719
|
+
response = await self._async_make_request("GET", url)
|
2720
|
+
return response.json().get("statuses", [])
|
2721
|
+
|
2722
|
+
def get_glossary_term_statuses(self) -> [str]:
|
2723
|
+
loop = asyncio.get_event_loop()
|
2724
|
+
response = loop.run_until_complete(self._async_get_glossary_term_statuses())
|
2725
|
+
return response
|
2726
|
+
|
2727
|
+
async def _async_get_glossary_term_rel_statuses(self) -> [str]:
|
2728
|
+
url = (f"{self.platform_url}/servers/{self.view_server}"
|
2729
|
+
f"/api/open-metadata/glossary-manager/glossaries/terms/relationships/status-list")
|
2730
|
+
response = await self._async_make_request("GET", url)
|
2731
|
+
return response.json().get("statuses", [])
|
2732
|
+
|
2733
|
+
def get_glossary_term_rel_statuses(self) -> [str]:
|
2734
|
+
loop = asyncio.get_event_loop()
|
2735
|
+
response = loop.run_until_complete(self._async_get_glossary_term_rel_statuses())
|
2736
|
+
return response
|
2737
|
+
|
2738
|
+
async def _async_get_glossary_term_activity_types(self) -> [str]:
|
2739
|
+
url = (f"{self.platform_url}/servers/{self.view_server}"
|
2740
|
+
f"/api/open-metadata/glossary-manager/glossaries/terms/activity-types")
|
2741
|
+
response = await self._async_make_request("GET", url)
|
2742
|
+
return response.json().get("types", [])
|
2743
|
+
|
2744
|
+
def get_glossary_term_activity_types(self) -> [str]:
|
2745
|
+
loop = asyncio.get_event_loop()
|
2746
|
+
response = loop.run_until_complete(self._async_get_glossary_term_statuses())
|
2747
|
+
return response
|
2748
|
+
|
2749
|
+
async def _async_get_term_relationship_types(self) -> [str]:
|
2750
|
+
url = (f"{self.platform_url}/servers/{self.view_server}"
|
2751
|
+
f"/api/open-metadata/glossary-manager/glossaries/terms/relationships/type-names")
|
2752
|
+
response = await self._async_make_request("GET", url)
|
2753
|
+
return response.json().get("names", [])
|
2754
|
+
|
2755
|
+
def get_term_relationship_types(self) -> [str]:
|
2756
|
+
loop = asyncio.get_event_loop()
|
2757
|
+
response = loop.run_until_complete(self._async_get_term_relationship_types())
|
2758
|
+
return response
|
2759
|
+
|
2760
|
+
async def _async_find_glossaries(self, search_string: str = "*", classificaton_names: list[str] = None,
|
2761
|
+
metadata_element_types: list[str] = ["Glossary"],
|
2762
|
+
starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False,
|
2763
|
+
start_from: int = 0,page_size: int = 0, output_format: str = 'JSON',
|
2764
|
+
output_format_set: str | dict = None,
|
2765
|
+
body: dict | SearchStringRequestBody = None) -> list | str:
|
2766
|
+
|
2767
|
+
response = await self._async_find_collections(search_string, classificaton_names,
|
2768
|
+
metadata_element_types, starts_with, ends_with, ignore_case,
|
2769
|
+
start_from, page_size, output_format, output_format_set, body)
|
2770
|
+
return response
|
2771
|
+
|
2772
|
+
def find_glossaries(self, search_string: str = "*", classificaton_names: list[str] = None,
|
2773
|
+
metadata_element_types: list[str] = ["Glossary"],
|
2774
|
+
starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False,
|
2775
|
+
start_from: int = 0,page_size: int = 0, output_format: str = 'JSON',
|
2776
|
+
output_format_set: str | dict = None,
|
2777
|
+
body: dict | SearchStringRequestBody = None) -> list | str:
|
2778
|
+
loop = asyncio.get_event_loop()
|
2779
|
+
response = loop.run_until_complete(
|
2780
|
+
self._async_find_glossaries(search_string, classificaton_names, metadata_element_types, starts_with, ends_with, ignore_case, start_from, page_size, output_format, output_format_set, body))
|
2781
|
+
return response
|
2782
|
+
|
2783
|
+
async def _async_get_glossaries_by_name(self, filter_string: str = None, classification_names: list[str] = None,
|
2784
|
+
body: dict | FilterRequestBody = None,
|
2785
|
+
start_from: int = 0, page_size: int = 0,
|
2786
|
+
output_format: str = 'JSON',
|
2787
|
+
output_format_set: str | dict = None) -> dict | str:
|
2788
|
+
return await self._async_get_collections_by_name(filter_string, classification_names, body, start_from, page_size, output_format, output_format_set)
|
2789
|
+
|
2790
|
+
|
2791
|
+
def get_glossaries_by_name(self, filter_string: str = None, classification_names: list[str] = None,
|
2792
|
+
body: dict | FilterRequestBody = None,
|
2793
|
+
start_from: int = 0, page_size: int = 0,
|
2794
|
+
output_format: str = 'JSON',
|
2795
|
+
output_format_set: str | dict = None) -> dict | str:
|
2796
|
+
loop = asyncio.get_event_loop()
|
2797
|
+
response = loop.run_until_complete(
|
2798
|
+
self._async_get_glossaries_by_name(filter_string, classification_names, body,start_from, page_size,
|
2799
|
+
output_format, output_format_set))
|
2800
|
+
return response
|
2801
|
+
|
2802
|
+
async def _async_get_glossary_by_guid(self, glossary_guid: str, element_type: str = "Glossary", body: dict | GetRequestBody = None,
|
2803
|
+
output_format: str = "JSON", output_format_set: str | dict = None) -> dict | str:
|
2804
|
+
|
2805
|
+
return await self._async_get_collection_by_guid(glossary_guid, element_type, body, output_format, output_format_set)
|
2806
|
+
|
2807
|
+
|
2808
|
+
|
2809
|
+
def get_glossary_by_guid(self, glossary_guid: str, element_type: str = "Glossary", body: dict| GetRequestBody=None,
|
2810
|
+
output_format: str = "JSON", output_format_set: str | dict = None) -> dict | str:
|
2811
|
+
loop = asyncio.get_event_loop()
|
2812
|
+
response = loop.run_until_complete(
|
2813
|
+
self._async_get_glossary_by_guid(glossary_guid, element_type, body,output_format, output_format_set))
|
2814
|
+
return response
|
2815
|
+
|
2816
|
+
|
2817
|
+
|
2818
|
+
async def _async_get_terms_by_name(self, filter_string: str = None, classification_names: list[str] = None,
|
2819
|
+
body: dict | FilterRequestBody = None,
|
2820
|
+
start_from: int = 0, page_size: int = 0,
|
2821
|
+
output_format: str = 'JSON',
|
2822
|
+
output_format_set: str | dict = None) -> list:
|
2823
|
+
url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/"
|
2824
|
+
f"terms/by-name")
|
2825
|
+
response = await self._async_get_name_request(url, _type="GlossaryTerm",
|
2826
|
+
_gen_output=self._generate_term_output,
|
2827
|
+
filter_string=filter_string,
|
2828
|
+
classification_names=classification_names,
|
2829
|
+
start_from=start_from, page_size=page_size,
|
2830
|
+
output_format=output_format, output_format_set=output_format_set,
|
2831
|
+
body=body)
|
2832
|
+
return response
|
2833
|
+
|
2834
|
+
def get_terms_by_name(self, filter_string: str = None, classification_names: list[str] = None,
|
2835
|
+
body: dict | FilterRequestBody = None,
|
2836
|
+
start_from: int = 0, page_size: int = 0,
|
2837
|
+
output_format: str = 'JSON',
|
2838
|
+
output_format_set: str | dict = None) -> list:
|
2839
|
+
loop = asyncio.get_event_loop()
|
2840
|
+
response = loop.run_until_complete(
|
2841
|
+
self._async_get_terms_by_name(filter_string, classification_names, body,start_from, page_size,
|
2842
|
+
output_format, output_format_set))
|
2843
|
+
return response
|
2844
|
+
|
2845
|
+
async def _async_get_term_by_guid(self, term_guid: str, element_type: str = "GlossaryTerm", body: dict| GetRequestBody=None,
|
2846
|
+
output_format: str = "JSON", output_format_set: str | dict = None) -> dict | str:
|
2847
|
+
url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms/"
|
2848
|
+
f"{term_guid}")
|
2849
|
+
response = await self._async_get_guid_request(url, _type=element_type,
|
2850
|
+
_gen_output=self._generate_term_output,
|
2851
|
+
output_format=output_format, output_format_set=output_format_set,
|
2852
|
+
body=body)
|
2853
|
+
return response
|
2854
|
+
|
2855
|
+
def get_term_by_guid(self, term_guid: str, element_type: str = "GlossaryTerm", body: dict| GetRequestBody=None,
|
2856
|
+
output_format: str = "JSON", output_format_set: str | dict = None) -> dict | str:
|
2857
|
+
loop = asyncio.get_event_loop()
|
2858
|
+
response = loop.run_until_complete(self._async_get_term_by_guid(term_guid, element_type, body, output_format, output_format_set))
|
2859
|
+
return response
|
2860
|
+
|
2861
|
+
async def _async_find_glossary_terms(self, search_string: str, starts_with: bool = False,
|
2862
|
+
ends_with: bool = False, ignore_case: bool = False, type_name: str = "GlossaryTerm",
|
2863
|
+
classification_names: list[str] = None, start_from: int = 0,
|
2864
|
+
page_size: int = 0, output_format: str = 'JSON',
|
2865
|
+
output_format_set: str | dict = None, body: dict = None) -> list | str:
|
2866
|
+
url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-manager/glossaries/terms/"
|
2867
|
+
f"by-search-string")
|
2868
|
+
response = await self._async_find_request(url, _type= type_name,
|
2869
|
+
_gen_output=self._generate_term_output,
|
2870
|
+
search_string = search_string, classification_names = classification_names,
|
2871
|
+
metadata_element_types = ["GlossaryTerm"],
|
2872
|
+
starts_with = starts_with, ends_with = ends_with, ignore_case = ignore_case,
|
2873
|
+
start_from = start_from, page_size = page_size,
|
2874
|
+
output_format=output_format, output_format_set=output_format_set,
|
2875
|
+
body=body)
|
2876
|
+
return response
|
2877
|
+
|
2878
|
+
def find_glossary_terms(self, search_string: str, starts_with: bool = False,
|
2879
|
+
ends_with: bool = False, ignore_case: bool = False, type_name: str = "GlossaryTerm",
|
2880
|
+
classification_names: list[str] = None, start_from: int = 0,
|
2881
|
+
page_size: int = 0, output_format: str = 'JSON',
|
2882
|
+
output_format_set: str | dict = None, body: dict = None) -> list | str:
|
2883
|
+
loop = asyncio.get_event_loop()
|
2884
|
+
response = loop.run_until_complete(
|
2885
|
+
self._async_find_glossary_terms(search_string, starts_with,
|
2886
|
+
ends_with, ignore_case, type_name,classification_names,
|
2887
|
+
start_from,
|
2888
|
+
page_size, output_format, output_format_set, body))
|
2889
|
+
return response
|
2890
|
+
|
2520
2891
|
|
2521
2892
|
if __name__ == "__main__":
|
2522
2893
|
print("Main-Glossary Manager")
|