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