pyegeria 5.3.9.9.3__py3-none-any.whl → 5.3.9.9.4__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.
Files changed (55) hide show
  1. md_processing/__init__.py +49 -0
  2. md_processing/commands.json +3252 -0
  3. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +254 -0
  4. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +696 -0
  5. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +254 -0
  6. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +298 -0
  7. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +608 -0
  8. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +94 -0
  9. md_processing/dr_egeria_inbox/archive/freddie_intro.md +284 -0
  10. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +275 -0
  11. md_processing/dr_egeria_inbox/archive/test-term.md +110 -0
  12. md_processing/dr_egeria_inbox/cat_test.md +100 -0
  13. md_processing/dr_egeria_inbox/data_field.md +54 -0
  14. md_processing/dr_egeria_inbox/data_spec.md +77 -0
  15. md_processing/dr_egeria_inbox/data_spec_test.md +2406 -0
  16. md_processing/dr_egeria_inbox/data_test.md +86 -0
  17. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +168 -0
  18. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +280 -0
  19. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +313 -0
  20. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +1073 -0
  21. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +44 -0
  22. md_processing/dr_egeria_inbox/glossary_creation_experiment.ipynb +341 -0
  23. md_processing/dr_egeria_inbox/glossary_test1.md +324 -0
  24. md_processing/dr_egeria_inbox/rel.md +8 -0
  25. md_processing/dr_egeria_inbox/sb.md +119 -0
  26. md_processing/dr_egeria_inbox/search_test.md +39 -0
  27. md_processing/dr_egeria_inbox/solution-components.md +154 -0
  28. md_processing/dr_egeria_inbox/solution_blueprints.md +118 -0
  29. md_processing/dr_egeria_inbox/synonym_test.md +42 -0
  30. md_processing/dr_egeria_inbox/t1.md +0 -0
  31. md_processing/dr_egeria_inbox/t2.md +268 -0
  32. md_processing/dr_egeria_outbox/processed-2025-05-15 19:52-data_test.md +94 -0
  33. md_processing/dr_egeria_outbox/processed-2025-05-16 07:39-data_test.md +88 -0
  34. md_processing/dr_egeria_outbox/processed-2025-05-17 16:01-data_field.md +56 -0
  35. md_processing/dr_egeria_outbox/processed-2025-05-18 15:51-data_test.md +103 -0
  36. md_processing/dr_egeria_outbox/processed-2025-05-18 16:47-data_test.md +94 -0
  37. md_processing/dr_egeria_outbox/processed-2025-05-19 07:14-data_test.md +96 -0
  38. md_processing/dr_egeria_outbox/processed-2025-05-19 07:20-data_test.md +100 -0
  39. md_processing/dr_egeria_outbox/processed-2025-05-19 07:22-data_test.md +88 -0
  40. md_processing/md_commands/__init__.py +3 -0
  41. md_processing/md_commands/blueprint_commands.py +303 -0
  42. md_processing/md_commands/data_designer_commands.py +1182 -0
  43. md_processing/md_commands/glossary_commands.py +1144 -0
  44. md_processing/md_commands/project_commands.py +163 -0
  45. md_processing/md_processing_utils/__init__.py +4 -0
  46. md_processing/md_processing_utils/common_md_proc_utils.py +724 -0
  47. md_processing/md_processing_utils/common_md_utils.py +172 -0
  48. md_processing/md_processing_utils/extraction_utils.py +486 -0
  49. md_processing/md_processing_utils/md_processing_constants.py +112 -0
  50. md_processing/md_processing_utils/message_constants.py +19 -0
  51. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.3.9.9.4.dist-info}/METADATA +1 -2
  52. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.3.9.9.4.dist-info}/RECORD +55 -5
  53. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.3.9.9.4.dist-info}/LICENSE +0 -0
  54. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.3.9.9.4.dist-info}/WHEEL +0 -0
  55. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.3.9.9.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1144 @@
1
+ """
2
+ This file contains glossary-related object_action functions for processing Egeria Markdown
3
+ """
4
+
5
+ import json
6
+ import os
7
+ import re
8
+ from typing import List, Optional
9
+
10
+ from rich import print
11
+ from rich.console import Console
12
+ from rich.markdown import Markdown
13
+
14
+ from md_processing.md_processing_utils.common_md_utils import (debug_level, print_msg, set_debug_level,
15
+ get_element_dictionary, update_element_dictionary)
16
+ from md_processing.md_processing_utils.extraction_utils import (extract_command_plus, extract_command,
17
+ process_simple_attribute, process_element_identifiers,
18
+ update_a_command, extract_attribute,
19
+ get_element_by_name, process_name_list)
20
+ from md_processing.md_processing_utils.md_processing_constants import (GLOSSARY_NAME_LABELS, TERM_NAME_LABELS,
21
+ TERM_RELATIONSHPS, PARENT_CATEGORY_LABELS,
22
+ CATEGORY_NAME_LABELS, ALWAYS, ERROR, INFO,
23
+ WARNING, pre_command, EXISTS_REQUIRED,
24
+ OUTPUT_LABELS, SEARCH_LABELS, GUID_LABELS,
25
+ ELEMENT_OUTPUT_FORMATS, command_seperator)
26
+ from pyegeria import body_slimmer
27
+ from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_ELEMENTS_FOUND, NO_CATEGORIES_FOUND)
28
+ from pyegeria.egeria_tech_client import EgeriaTech
29
+
30
+ EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
31
+ console = Console(width=EGERIA_WIDTH)
32
+
33
+
34
+ def update_term_categories(egeria_client: EgeriaTech, term_guid: str, categories_exist: bool,
35
+ categories_list: List[str]) -> None:
36
+ """
37
+
38
+ Adds or removes a term to/from specified categories in a glossary.
39
+
40
+ This function associates a term, identified by its GUID, with one or more
41
+ categories. It uses the provided EgeriaTech client to assign the term
42
+ to the categories. If the GUID of a category is not readily available, it
43
+ is retrieved either from a pre-loaded dictionary or through a client lookup.
44
+
45
+ Args:
46
+ egeria_client (EgeriaTech): The client to interact with the glossary.
47
+ term_guid (str): The GUID of the term to be associated with categories.
48
+ categories_exist (bool): Flag indicating whether the categories already
49
+ exist.
50
+ categories_list (List[str]): A list of category names to associate with
51
+ the term.
52
+
53
+ Returns:
54
+ None
55
+ """
56
+ to_be_cat_guids: list[str] = []
57
+ # find the categories a term is currently in.
58
+ existing_categories = egeria_client.get_categories_for_term(term_guid)
59
+ if type(existing_categories) is str:
60
+ current_categories = []
61
+ else:
62
+ current_categories = [cat['elementHeader']['guid'] for cat in existing_categories]
63
+
64
+ if categories_exist is True and categories_list is not None:
65
+ if type(categories_list) is str:
66
+ categories_list = categories_list.split(",").trim()
67
+ for category in categories_list:
68
+ cat_guid = None
69
+ cat_el = category.strip()
70
+ element_dict = get_element_dictionary()
71
+ if cat_el in element_dict:
72
+ cat = element_dict.get(cat_el, None)
73
+ cat_guid = cat.get('guid', None) if cat else None
74
+ if cat_guid is None:
75
+ cat_guid = egeria_client.__get_guid__(qualified_name=cat_el)
76
+ update_element_dictionary(cat_el, {'guid': cat_guid})
77
+ to_be_cat_guids.append(cat_guid)
78
+
79
+ for cat in to_be_cat_guids:
80
+ if cat not in current_categories:
81
+ egeria_client.add_term_to_category(term_guid, cat)
82
+ current_categories.append(cat)
83
+ msg = f"Added term {term_guid} to category {cat}"
84
+ print_msg("DEBUG-INFO", msg, debug_level)
85
+
86
+ for cat in current_categories:
87
+ if cat not in to_be_cat_guids:
88
+ egeria_client.remove_term_from_category(term_guid, cat)
89
+ msg = f"Removed term {term_guid} from category {cat}"
90
+ print_msg("DEBUG-INFO", msg, debug_level)
91
+ else: # No categories specified - so remove any categories a term is in
92
+ for cat in current_categories:
93
+ egeria_client.remove_term_from_category(term_guid, cat)
94
+ msg = f"Removed term {term_guid} from category {cat}"
95
+ print_msg("DEBUG-INFO", msg, debug_level)
96
+
97
+
98
+ # def update_term_categories(egeria_client: EgeriaTech, term_guid: str, current_categories: List[str],
99
+ # new_categories: List[str]) -> None:
100
+ # """
101
+ # Updates the categories of a term.
102
+ #
103
+ # Args:
104
+ # egeria_client: The Egeria client to use for the update.
105
+ # term_guid: The GUID of the term to update.
106
+ # current_categories: The current categories of the term.
107
+ # new_categories: The new categories of the term.
108
+ # """
109
+ # if new_categories: # If categories are specified, add them
110
+ # for cat in new_categories:
111
+ # if cat not in current_categories:
112
+ # egeria_client.add_term_to_category(term_guid, cat)
113
+ # msg = f"Added term {term_guid} to category {cat}"
114
+ # print_msg("DEBUG-INFO", msg, debug_level)
115
+ # # Remove any categories that are not in the new list
116
+ # for cat in current_categories:
117
+ # if cat not in new_categories:
118
+ # egeria_client.remove_term_from_category(term_guid, cat)
119
+ # msg = f"Removed term {term_guid} from category {cat}"
120
+ # print_msg("DEBUG-INFO", msg, debug_level)
121
+ # else: # No categories specified - so remove any categories a term is in
122
+ # for cat in current_categories:
123
+ # egeria_client.remove_term_from_category(term_guid, cat)
124
+ # msg = f"Removed term {term_guid} from category {cat}"
125
+ # print_msg("DEBUG-INFO", msg, debug_level)
126
+
127
+
128
+ def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
129
+ """
130
+ Processes a glossary create or update object_action by extracting key attributes such as
131
+ glossary name, language, description, and usage from the given text.
132
+
133
+ :param txt: A string representing the input cell to be processed for
134
+ extracting glossary-related attributes.
135
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
136
+ :return: A string summarizing the outcome of the processing.
137
+ """
138
+
139
+ command, object_type, object_action = extract_command_plus(txt)
140
+ set_debug_level(directive)
141
+
142
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
143
+ print(Markdown(
144
+ f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `"
145
+ f"{directive}` "))
146
+ language = process_simple_attribute(txt, ['Language'], INFO)
147
+ description = process_simple_attribute(txt, ['Description'], INFO)
148
+ usage = process_simple_attribute(txt, ['Usage'], INFO)
149
+ q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
150
+ valid = True
151
+
152
+ if glossary_name is None:
153
+ valid = False
154
+ known_q_name = None
155
+ known_guid = None
156
+ glossary_exists = False
157
+ else:
158
+ element_labels = GLOSSARY_NAME_LABELS
159
+ element_labels.append('Display Name')
160
+ known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,
161
+ element_labels, txt,
162
+ object_action, None)
163
+ glossary_display = (f"\n* Command: `{command}`\n\t* Glossary Name: {glossary_name}\n\t"
164
+ f"* Language: {language}\n\t* Description:\n{description}\n"
165
+ f"* Usage: {usage}\n")
166
+
167
+ if object_action == 'Update':
168
+ guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
169
+ glossary_display += f"* Qualified Name: `{q_name}`\n\t* GUID: {guid}\n\n"
170
+ if not glossary_exists:
171
+ msg = f"Glossary can't be updated; `{glossary_name}` not found"
172
+ print_msg("ERROR", msg, debug_level)
173
+ valid = False
174
+ else:
175
+ msg = f"Glossary can be updated; `{glossary_name}` found"
176
+ print_msg(ALWAYS, msg, debug_level)
177
+
178
+
179
+ elif object_action == "Create":
180
+ if glossary_exists:
181
+ msg = f"Glossary `{glossary_name}` can't be created because it already exists.\n"
182
+ print_msg("ERROR", msg, debug_level)
183
+ valid = False
184
+ elif valid:
185
+ msg = f"It is valid to create Glossary `{glossary_name}` with:\n"
186
+ print_msg("ALWAYS", msg, debug_level)
187
+
188
+ if directive == "display":
189
+ print(Markdown(glossary_display))
190
+ return None
191
+
192
+ elif directive == "validate":
193
+ if valid:
194
+ print(Markdown(glossary_display))
195
+ else:
196
+ msg = f"Validation failed for Glossary `{glossary_name}`\n"
197
+ print_msg(ERROR, msg, debug_level)
198
+ print(Markdown(glossary_display))
199
+
200
+ return valid
201
+
202
+ elif directive == "process":
203
+ if valid:
204
+ print(Markdown(glossary_display))
205
+ else:
206
+ if glossary_exists and object_action == "Create":
207
+ msg = (f"Create failed because glossary `{glossary_name}` exists - changing `Create` to `Update` in "
208
+ f"processed output \n")
209
+ print_msg(ERROR, msg, debug_level)
210
+ print(Markdown(glossary_display))
211
+ print(command_seperator)
212
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
213
+ else:
214
+ return None
215
+ if object_action == "Update":
216
+ if not glossary_exists:
217
+ print(f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
218
+ f"object_action\n")
219
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
220
+
221
+ body = {
222
+ "class": "ReferenceableRequestBody", "elementProperties": {
223
+ "class": "GlossaryProperties", "qualifiedName": known_q_name, "description": description,
224
+ "language": language, "usage": usage
225
+ }
226
+ }
227
+ egeria_client.update_glossary(known_guid, body)
228
+ print_msg(ALWAYS, f"Updated Glossary `{glossary_name}` with GUID {known_guid}", debug_level)
229
+ update_element_dictionary(known_q_name, {
230
+ 'guid': known_guid, 'display_name': glossary_name
231
+ })
232
+ return egeria_client.get_glossary_by_guid(known_guid, output_format='MD')
233
+ elif object_action == "Create":
234
+ glossary_guid = None
235
+
236
+ if glossary_exists:
237
+ print(f"\nGlossary `{glossary_name}` already exists and result document updated\n")
238
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
239
+ else:
240
+ glossary_guid = egeria_client.create_glossary(glossary_name, description, language, usage)
241
+ glossary = egeria_client.get_glossary_by_guid(glossary_guid)
242
+ if glossary == NO_GLOSSARIES_FOUND:
243
+ print(f"{ERROR}Just created with GUID {glossary_guid} but Glossary not found\n")
244
+ return None
245
+ qualified_name = glossary['glossaryProperties']["qualifiedName"]
246
+ update_element_dictionary(qualified_name, {
247
+ 'guid': glossary_guid, 'display_name': glossary_name
248
+ })
249
+ # return update_a_command(txt, object_action, object_type, qualified_name, glossary_guid)
250
+ print_msg(ALWAYS, f"Created Glossary `{glossary_name}` with GUID {glossary_guid}", debug_level)
251
+ return egeria_client.get_glossary_by_guid(glossary_guid, output_format='FORM')
252
+ else:
253
+ return None
254
+ else:
255
+ return None
256
+
257
+
258
+ def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
259
+ """
260
+ Processes a glossary category create or update object_action by extracting key attributes such as
261
+ category name, qualified, description, and anchor glossary from the given txt..
262
+
263
+ :param txt: A string representing the input cell to be processed for
264
+ extracting category-related attributes.
265
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
266
+ :return: A string summarizing the outcome of the processing.
267
+ """
268
+ valid = True
269
+ set_debug_level(directive)
270
+
271
+ command, object_type, object_action = extract_command_plus(txt)
272
+
273
+ category_name = process_simple_attribute(txt, ['Category Name', 'category_name', 'Cat'])
274
+ print(Markdown(f"{pre_command} `{command}` for category: `\'{category_name}\'` with directive: `{directive}` "))
275
+
276
+ owning_glossary_name = extract_attribute(txt, ['Owning Glossary', 'In Glossary'])
277
+ description = process_simple_attribute(txt, ['Description'])
278
+ q_name = process_simple_attribute(txt, ['Qualified Name'])
279
+
280
+ parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS, "INFO")
281
+
282
+ element_labels = CATEGORY_NAME_LABELS
283
+ element_labels.append('Display Name')
284
+ # Check if category exists (and get qname and guid)
285
+ if category_name is None:
286
+ valid = False
287
+ known_q_name, known_guid, category_exists = None
288
+ else:
289
+ element_labels = CATEGORY_NAME_LABELS
290
+ element_labels.append('Display Name')
291
+ known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type,
292
+ element_labels, txt,
293
+ object_action, None)
294
+
295
+ # Check if owning glossary exists (and get qname)
296
+ if owning_glossary_name is None:
297
+ valid = False
298
+ known_glossary_q_name, known_glossary__guid, glossary_exists = None
299
+
300
+ else:
301
+ known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(
302
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
303
+
304
+ if parent_category_name:
305
+ _, parent_guid, parent_valid, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
306
+ parent_category_name)
307
+ else:
308
+ parent_guid = None
309
+ parent_exists = False
310
+ parent_valid = False
311
+
312
+ category_display = (
313
+ f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_name}\n\t"
314
+ f"* Description:\n{description}\n\t* Parent Category: {parent_category_name}\n\t"
315
+ f"* Qualified Name: {q_name}\n\t")
316
+
317
+ if object_action == 'Update':
318
+ guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
319
+
320
+ category_display += (f"* GUID: {guid}\n\n")
321
+ if not category_exists:
322
+ msg = f"Category {category_name} can't be updated; {category_name} not found."
323
+ print_msg(ERROR, msg, debug_level)
324
+ valid = False
325
+ else:
326
+ msg = f"Glossary can be updated; {category_name} found"
327
+ print_msg(ALWAYS, msg, debug_level)
328
+
329
+ elif object_action == "Create":
330
+ if category_exists:
331
+ msg = f"Category {category_name} can't be created because it already exists.\n"
332
+ print_msg("ERROR", msg, debug_level)
333
+ valid = False
334
+ elif valid:
335
+ msg = f"It is valid to create Category `{category_name}` with:\n"
336
+ print_msg("ALWAYS", msg, debug_level)
337
+
338
+ if directive == "display":
339
+ print(Markdown(category_display))
340
+ return None
341
+
342
+ elif directive == "validate":
343
+ if valid:
344
+ print(Markdown(category_display))
345
+ else:
346
+ msg = f"Validation failed for {object_type} `{category_name}`\n"
347
+ print_msg(ERROR, msg, debug_level)
348
+ print(Markdown(category_display))
349
+ return valid
350
+
351
+ elif directive == "process":
352
+ if valid:
353
+ print(Markdown(category_display))
354
+ else:
355
+ if category_exists and object_action == "Create":
356
+ msg = (f"Create failed because category `{category_name}` exists - changing `Create` to `Update` in "
357
+ f"processed output \n")
358
+ print_msg(ERROR, msg, debug_level)
359
+ print(Markdown(category_display))
360
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
361
+ else:
362
+ return None
363
+
364
+ if object_action == "Update":
365
+ if not category_exists:
366
+ print(f"\n{ERROR}category `{category_name}` does not exist! Updating result document with Create "
367
+ f"object_action\n")
368
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
369
+
370
+ # Update the basic category properties
371
+ egeria_client.update_category(known_guid, category_name, description, known_q_name, None)
372
+ msg = f"->Updated category `{category_name}`with GUID {known_guid}"
373
+ print_msg(ALWAYS, msg, debug_level)
374
+
375
+ # Update parent-child relationships
376
+
377
+ update_element_dictionary(known_q_name, {
378
+ 'guid': known_guid, 'display_name': category_name
379
+ })
380
+
381
+ category_sync = update_category_parent(egeria_client, known_guid, parent_category_name)
382
+ print_msg(ALWAYS, f"Updated Category hierarchy for `{category_name}` with outcome {category_sync}",
383
+ debug_level)
384
+ return egeria_client.get_category_by_guid(known_guid, output_format='FORM')
385
+
386
+ elif object_action == "Create":
387
+ is_root = True
388
+
389
+ if category_exists:
390
+ msg = (f"Cannot create`{category_name}` because it already exists; result document written for "
391
+ f"category update\n")
392
+ print_msg(WARNING, msg, debug_level)
393
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
394
+ else:
395
+ category_guid = egeria_client.create_category(known_glossary_guid, category_name, description, is_root)
396
+ category_details = egeria_client.get_category_by_guid(category_guid)
397
+
398
+ if category_details == NO_CATEGORIES_FOUND:
399
+ msg = f"Just created category with GUID {category_guid} but category not found"
400
+ print_msg(ERROR, msg, debug_level)
401
+ return None
402
+
403
+ qualified_name = category_details['glossaryCategoryProperties']["qualifiedName"]
404
+ update_element_dictionary(qualified_name, {
405
+ 'guid': category_guid, 'display_name': category_name
406
+ })
407
+ print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
408
+ if parent_valid and parent_guid:
409
+ egeria_client.set_parent_category(parent_guid, category_guid)
410
+ print_msg(ALWAYS, f"Set parent category for `{category_name}` to `{parent_category_name}`",
411
+ debug_level)
412
+ else:
413
+ print_msg(ERROR,
414
+ f"Parent category `{parent_category_name}` not found or invalid for `{category_name}`",
415
+ debug_level)
416
+ return egeria_client.get_category_by_guid(category_guid, output_format='FORM')
417
+ return None
418
+ return None
419
+
420
+
421
+ def update_category_parent(egeria_client, category_guid: str, parent_category_name: str = None) -> bool:
422
+ """
423
+ Updates the parent relationship for a category.
424
+
425
+ If a parent category is specified, it will check if a parent is currently set.
426
+ If a parent category was set and is the same as the parent category specified, no change is needed.
427
+ If a parent category was set and is different from the parent_category_name, the parent category is updated.
428
+ If parent_category_name is None or empty and an existing parent category was set, the parent category is removed.
429
+
430
+ Parameters
431
+ ----------
432
+ egeria_client: EgeriaTech
433
+ The Egeria client to use for API calls
434
+ category_guid: str
435
+ The GUID of the category to update
436
+ parent_category_name: str, optional
437
+ The name of the parent category to set, or None to remove the parent
438
+
439
+ Returns
440
+ -------
441
+
442
+ True if successful, False otherwise.
443
+
444
+ """
445
+ outcome = True
446
+ # Handle parent category updates
447
+ if parent_category_name:
448
+ # Check if a parent is currently set
449
+ current_parent = egeria_client.get_category_parent(category_guid)
450
+
451
+ if isinstance(current_parent, str) and "No Parent Category found" in current_parent:
452
+ # No parent currently set, need to set it
453
+ _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
454
+ parent_category_name)
455
+
456
+ if parent_exists and parent_guid:
457
+ egeria_client.set_parent_category(parent_guid, category_guid)
458
+ print_msg(ALWAYS, f"Set parent category of category to `{parent_category_name}`", debug_level)
459
+ else:
460
+ print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
461
+ outcome = False
462
+ else:
463
+ # Parent is set, check if it's the same
464
+ current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
465
+
466
+ if current_parent_name != parent_category_name:
467
+ # Different parent, need to update
468
+ # First remove the current parent
469
+ current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
470
+ if current_parent_guid:
471
+ egeria_client.remove_parent_category(current_parent_guid, category_guid)
472
+
473
+ # Then set the new parent
474
+ _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
475
+ parent_category_name)
476
+
477
+ if parent_exists and parent_guid:
478
+ egeria_client.set_parent_category(parent_guid, category_guid)
479
+ print_msg(ALWAYS,
480
+ f"Updated parent category from `{current_parent_name}` to `{parent_category_name}`",
481
+ debug_level)
482
+ else:
483
+ print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
484
+ outcome = False
485
+ elif parent_category_name is None or parent_category_name == '':
486
+ # Check if a parent is currently set and remove it if needed
487
+ current_parent = egeria_client.get_category_parent(category_guid)
488
+
489
+ if not isinstance(current_parent, str) or "No Parent Category found" not in current_parent:
490
+ # Parent is set, need to remove it
491
+ current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
492
+ current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
493
+
494
+ if current_parent_guid:
495
+ egeria_client.remove_parent_category(current_parent_guid, category_guid)
496
+ print_msg(ALWAYS, f"Removed parent category `{current_parent_name}`", debug_level)
497
+
498
+ return outcome
499
+
500
+
501
+ def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
502
+ """
503
+ Processes a term create or update object_action by extracting key attributes such as
504
+ term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
505
+
506
+ :param txt: A string representing the input cell to be processed for
507
+ extracting glossary-related attributes.
508
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
509
+ :return: A string summarizing the outcome of the processing.
510
+ """
511
+ valid = True
512
+ categories_list = None
513
+ cats_exist = False
514
+ set_debug_level(directive)
515
+ known_q_name = None
516
+ command = extract_command(txt)
517
+ object_type = command.split(' ')[1].strip()
518
+ object_action = command.split(' ')[0].strip()
519
+
520
+ term_name = process_simple_attribute(txt, ['Term Name', 'Display Name'], ERROR)
521
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
522
+ summary = process_simple_attribute(txt, ['Summary'], INFO)
523
+ description = process_simple_attribute(txt, ['Description'], INFO)
524
+ abbreviation = process_simple_attribute(txt, ['Abbreviation'], INFO)
525
+ examples = process_simple_attribute(txt, ['Examples'], INFO)
526
+ usage = process_simple_attribute(txt, ['Usage'], INFO)
527
+ status = process_simple_attribute(txt, ['Status'])
528
+ status = status.upper() if status else 'DRAFT'
529
+ version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"], INFO)
530
+ q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
531
+
532
+ aliases = process_simple_attribute(txt, ['Aliases', 'Alias'], INFO)
533
+ if aliases:
534
+ alias_list = list(filter(None, re.split(r'[,\n]+', aliases.strip())))
535
+ else:
536
+ alias_list = None
537
+
538
+ # validate term name and get existing qualified_name and guid if they exist
539
+ if term_name is None:
540
+ valid = False
541
+ known_q_name, known_guid, term_exists = None
542
+ else:
543
+ element_labels = TERM_NAME_LABELS
544
+ element_labels.append('Display Name')
545
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
546
+ element_labels, txt, object_action,
547
+ version)
548
+
549
+ # get the glossary qualified name this term is in
550
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
551
+ if glossary_name is None:
552
+ valid = False
553
+ known_glossary_guid = None
554
+ known_glossary_q_name = None
555
+ glossary_valid = False
556
+ glossary_exists = False
557
+ else:
558
+ known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
559
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
560
+
561
+ # process categories, if present
562
+ categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
563
+ if categories: # Find information about categoriess that classify this term
564
+ msg = "Checking for categories that classify this term"
565
+ print_msg("DEBUG-INFO", msg, debug_level)
566
+ categories_list, cat_q_name_list, cats_valid, cats_exist = process_name_list(egeria_client,
567
+ 'Glossary Categories', txt,
568
+ CATEGORY_NAME_LABELS)
569
+ if cats_exist and cats_valid:
570
+ msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
571
+ print_msg("INFO", msg, debug_level)
572
+ else:
573
+ msg = "No valid glossary categories found."
574
+ print_msg("INFO", msg, debug_level)
575
+ else:
576
+ cats_exist = cats_valid = False
577
+ cat_q_name_list = None
578
+
579
+ if object_action == "Update": # check to see if provided information exists and is consistent with existing info
580
+ term_guid = process_simple_attribute(txt, GUID_LABELS)
581
+ update_description = process_simple_attribute(txt, ['Update Description'])
582
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
583
+ f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t"
584
+ f"* Categories: {categories}\n\t"
585
+ f"* Summary: {summary}\n\t* Description: {description}\n\t"
586
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
587
+ f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}"
588
+ f"\n\t* Update Description: {update_description}\n")
589
+ if not term_exists:
590
+ msg = f"Update request invalid, Term {term_name} does not exist\n"
591
+ print_msg(ERROR, msg, debug_level)
592
+ valid = False
593
+
594
+ elif object_action == 'Create': # if the object_action is create, check that it doesn't already exist
595
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
596
+ f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
597
+ f"* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t* Description: {description}\n\t"
598
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
599
+ f"* Version: {version}\n\t* Status: {status}\n")
600
+ if term_exists:
601
+ msg = f"Term `{term_name}` cannot be created since it already exists\n"
602
+ print_msg(ERROR, msg, debug_level)
603
+ else:
604
+ msg = f"It is valid to create Term `{term_name}`"
605
+ print_msg(ALWAYS, msg, debug_level)
606
+
607
+ if directive == "display":
608
+ print(Markdown(term_display))
609
+ return None
610
+ elif directive == "validate":
611
+ print(Markdown(term_display))
612
+ return valid
613
+ elif directive == "process":
614
+ try:
615
+ if not valid: # First validate the term before we process it
616
+ if term_exists and object_action == "Create":
617
+ msg = (f"Create failed because term `{term_name}` exists - changing `Create` to `Update` in "
618
+ f"processed output \n")
619
+ print_msg(ERROR, msg, debug_level)
620
+ print(Markdown(term_display))
621
+ return update_a_command(txt, object_action, object_type, known_q_name, known_guid)
622
+ else:
623
+ return None
624
+
625
+ print(Markdown(term_display))
626
+ if object_action == "Update" and directive == "process":
627
+ if not term_exists:
628
+ return None
629
+ body = {
630
+ "class": "ReferenceableRequestBody", "elementProperties": {
631
+ "displayName": term_name, "class": "GlossaryTermProperties", "qualifiedName": known_q_name,
632
+ "aliases": alias_list, "summary": summary, "description": description,
633
+ "abbreviation": abbreviation, "examples": examples, "usage": usage,
634
+ "publishVersionIdentifier": version, "status": status
635
+ }, "updateDescription": update_description
636
+ }
637
+ egeria_client.update_term(known_guid, body_slimmer(body), is_merge_update=False)
638
+ # if cat_exist and cat_valid:
639
+ update_term_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
640
+ print_msg(ALWAYS,
641
+ f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
642
+ debug_level)
643
+ return egeria_client.get_term_by_guid(known_guid,
644
+ 'md') # return update_a_command(txt, object_action, object_type,
645
+ # known_q_name, known_guid)
646
+ elif object_action == "Update" and directive == "validate": # is sthis reachable?
647
+ return egeria_client.get_term_by_guid(known_guid, 'md')
648
+
649
+ elif object_action == "Create":
650
+ if term_exists:
651
+ msg = f"Term {term_name} exists so result document modifies term create to term update"
652
+ print_msg(INFO, msg, debug_level)
653
+ return update_a_command(txt, object_action, object_type, q_name, known_guid)
654
+ else:
655
+ ## get the guid for the glossary from the name - first look in cache
656
+ cached = get_element_dictionary().get(known_glossary_q_name, None)
657
+
658
+ if cached is not None:
659
+ glossary_guid = cached.get('guid', None)
660
+ if glossary_guid is None:
661
+ msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
662
+ print_msg(WARNING, msg, debug_level) # should this ever occur?
663
+ return None
664
+ else:
665
+ glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
666
+ if glossary_guid == NO_ELEMENTS_FOUND:
667
+ msg = f"Glossary {known_glossary_q_name} not found"
668
+ print_msg(WARNING, msg, debug_level)
669
+ return None
670
+ term_body = {
671
+ "class": "ReferenceableRequestBody", "elementProperties": {
672
+ "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "displayName": term_name,
673
+ "aliases": alias_list, "summary": summary, "description": description,
674
+ "abbreviation": abbreviation, "examples": examples, "usage": usage,
675
+ "publishVersionIdentifier": version
676
+ # "additionalProperties":
677
+ # {
678
+ # "propertyName1": "xxxx",
679
+ # "propertyName2": "xxxx"
680
+ # }
681
+ }, "initialStatus": status
682
+ }
683
+ term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, body_slimmer(term_body))
684
+ if term_guid == NO_ELEMENTS_FOUND:
685
+ print(f"{ERROR}Term {term_name} not created")
686
+ return None
687
+ if cats_exist and categories is not None:
688
+ update_term_categories(egeria_client, term_guid, cats_exist, cat_q_name_list)
689
+ update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
690
+ print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
691
+ return egeria_client.get_term_by_guid(term_guid,
692
+ 'MD') # return update_a_command(txt, object_action,
693
+ # object_type, q_name, term_guid)
694
+ except Exception as e:
695
+ print(f"{ERROR}Error creating term {term_name}: {e}")
696
+ console.print_exception(show_locals=True)
697
+ return None
698
+ else:
699
+ return None
700
+
701
+
702
+ def process_create_term_term_relationship_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
703
+ Optional[str]:
704
+ """ Relate two terms through the specified relationship. ."""
705
+ set_debug_level(directive)
706
+ valid = True
707
+ command = extract_command(txt)
708
+ object_type = command.split(' ')[1].strip()
709
+ object_action = command.split(' ')[0].strip()
710
+ term1_guid = None
711
+ term2_guid = None
712
+
713
+ term_relationship = process_simple_attribute(txt, ["Term Relationship", "Relationship Type"], "ERROR")
714
+ if term_relationship not in TERM_RELATIONSHPS:
715
+ valid = False
716
+
717
+ print(Markdown(
718
+ f"{pre_command} `{command}` for term relationship: `{term_relationship}` with directive: `{directive}` "))
719
+
720
+ term1_q_name, term1_guid, term1_valid, term1_exists = process_element_identifiers(egeria_client, object_type,
721
+ ["Term 1 Name", "Term 1"], txt,
722
+ "Exists Required", None)
723
+
724
+ term2_q_name, term2_guid, term2_valid, term2_exists = process_element_identifiers(egeria_client, object_type,
725
+ ["Term 2 Name", "Term 2"], txt,
726
+ "Exists Required", None)
727
+
728
+ request_display = (f"\n\t* Term 1 Qualified Name: {term1_q_name}\n\t* Term 2 Qualified Name {term2_q_name}\n\t"
729
+ f"* Term Relationship: {term_relationship}")
730
+
731
+ if not (term1_valid and term2_valid and term1_exists and term2_exists):
732
+ valid = False
733
+
734
+ if directive == "display":
735
+ print(request_display)
736
+ return None
737
+ elif directive == "validate":
738
+ print(request_display)
739
+ return str(valid)
740
+ elif directive == "process":
741
+ try:
742
+ print(request_display)
743
+ if not valid: # First validate the term before we process it
744
+ return None
745
+ egeria_client.add_relationship_between_terms(term1_guid, term2_guid, term_relationship)
746
+ print_msg(ALWAYS, f"Relationship `{term_relationship}` created", debug_level)
747
+ update_md = (f"\n\n# Update Term-Term Relationship\n\n## Term 1 Name:\n\n{term1_q_name}"
748
+ f"\n\n## Term 2 Name\n\n{term2_q_name}\n\n## Term Relationship:\n\n{term_relationship}")
749
+ return update_md
750
+
751
+
752
+ except Exception as e:
753
+ print(f"{ERROR}Error performing {command}: {e}")
754
+ console.print_exception(show_locals=True)
755
+ return None
756
+ else:
757
+ return None
758
+
759
+
760
+ def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
761
+ """ List terms as a markdown table. Filter based on optional search string. """
762
+ set_debug_level(directive)
763
+ valid = True
764
+ command = extract_command(txt)
765
+
766
+ search_string = process_simple_attribute(txt, SEARCH_LABELS)
767
+ if search_string is None:
768
+ search_string = '*'
769
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
770
+
771
+ glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary', "Glossary Name"])
772
+ if glossary is not None:
773
+ _, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
774
+ msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
775
+ print_msg(INFO, msg, debug_level)
776
+ else:
777
+ glossary_guid = None
778
+ msg = f"No glossary found"
779
+ print_msg(INFO, msg, debug_level)
780
+
781
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS)
782
+ if output_format is None:
783
+ output_format = "LIST"
784
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
785
+ valid = False
786
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
787
+
788
+ request_display = (f"\n\t* Search String: {search_string}\n\t* Glossary: {glossary}\n\t* Output Format: "
789
+ f"{output_format}\n")
790
+
791
+ if directive == "display":
792
+ print(Markdown(request_display))
793
+ return None
794
+ elif directive == "validate":
795
+ print(Markdown(request_display))
796
+ return valid
797
+ elif directive == "process":
798
+ try:
799
+ print(Markdown(request_display))
800
+ if not valid: # First validate the term before we process it
801
+ return None
802
+
803
+ term_list_md = f"\n# Term List for search string: `{search_string}`\n\n"
804
+ if output_format == "DICT":
805
+ struct = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
806
+ term_list_md += f"```{json.dumps(struct, indent=4)}```\n"
807
+ else:
808
+ term_list_md += egeria_client.find_glossary_terms(search_string, glossary_guid,
809
+ output_format=output_format)
810
+ print_msg("ALWAYS", f"Wrote Term List for search string: `{search_string}`", debug_level)
811
+
812
+ return term_list_md
813
+
814
+ md_table = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
815
+
816
+ print_msg("ALWAYS", f"Wrote Term list for search string `{search_string}`", debug_level)
817
+ return md_table
818
+
819
+ except Exception as e:
820
+ print(f"{ERROR}Error performing {command}: {e}")
821
+ console.print_exception(show_locals=True)
822
+ return None
823
+ else:
824
+ return None
825
+
826
+
827
+ def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
828
+ """ List terms as a markdown table. Filter based on optional search string. """
829
+ set_debug_level(directive)
830
+ valid = True
831
+ command = extract_command(txt)
832
+
833
+ search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
834
+ if search_string is None:
835
+ search_string = '*'
836
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
837
+
838
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
839
+ if output_format is None:
840
+ output_format = "LIST"
841
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
842
+ valid = False
843
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
844
+
845
+ request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
846
+
847
+ if directive == "display":
848
+ print(Markdown(request_display))
849
+ return None
850
+ elif directive == "validate":
851
+ print(Markdown(request_display))
852
+ return valid
853
+ elif directive == "process":
854
+ try:
855
+ print(Markdown(request_display))
856
+ if not valid: # First validate the term before we process it
857
+ return None
858
+
859
+ cat_list_md = f"\n# Category List for search string: `{search_string}`\n\n"
860
+ if output_format == "DICT":
861
+ struct = egeria_client.find_glossary_categories(search_string, output_format=output_format)
862
+ cat_list_md += f"```{json.dumps(struct, indent=4)}```\n"
863
+ else:
864
+ cat_list_md += egeria_client.find_glossary_categories(search_string, output_format=output_format)
865
+ print_msg("ALWAYS", f"Wrote Category List for search string: `{search_string}`", debug_level)
866
+
867
+ return cat_list_md
868
+
869
+ except Exception as e:
870
+ print(f"{ERROR}Error performing {command}: {e}")
871
+ console.print_exception(show_locals=True)
872
+ return None
873
+ else:
874
+
875
+ return None
876
+
877
+
878
+ def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
879
+ str]:
880
+ """ List terms as a markdown table. Filter based on optional search string. """
881
+ set_debug_level(directive)
882
+ valid = True
883
+ command = extract_command(txt)
884
+
885
+ known_glossary_guid = ""
886
+
887
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, "ERROR")
888
+
889
+ _, known_glossary_guid, valid, _ = process_element_identifiers(egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt,
890
+ EXISTS_REQUIRED, None)
891
+
892
+ print(Markdown(f"{pre_command} `{command}` for glossary:`{glossary_name}` with directive: `{directive}`"))
893
+
894
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
895
+ if output_format is None:
896
+ output_format = "MD"
897
+ elif output_format not in ["DICT", "LIST", "MD"]:
898
+ valid = False
899
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
900
+
901
+ request_display = f"\n\t* Glossary name: {glossary_name}\n\t* Output Format: {output_format}\n"
902
+
903
+ if directive == "display":
904
+ print(Markdown(request_display))
905
+ return None
906
+ elif directive == "validate":
907
+ print(Markdown(request_display))
908
+ return str(valid)
909
+ elif directive == "process":
910
+ try:
911
+ print(Markdown(request_display))
912
+ if not valid: # First validate the term before we process it
913
+ return None
914
+
915
+ glossary_structure_md = f"\n# Glossary Structure for `{glossary_name}`\n\n"
916
+ if output_format == "DICT":
917
+ struct = egeria_client.get_glossary_category_structure(known_glossary_guid, output_format=output_format)
918
+ glossary_structure_md += f"```{json.dumps(struct, indent=4)}```\n"
919
+ else:
920
+ glossary_structure_md += egeria_client.get_glossary_category_structure(known_glossary_guid,
921
+ output_format=output_format)
922
+ print_msg("ALWAYS", f"Wrote Glossary Structure for glossary: `{glossary_name}`", debug_level)
923
+
924
+ return glossary_structure_md
925
+
926
+ except Exception as e:
927
+ print(f"{ERROR}Error performing {command}: {e}")
928
+ console.print_exception(show_locals=True)
929
+ return None
930
+ else:
931
+ return None
932
+
933
+
934
+ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
935
+ """ List terms as a markdown table. Filter based on optional search string. """
936
+ set_debug_level(directive)
937
+ valid = True
938
+ command = extract_command(txt)
939
+
940
+ search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
941
+ if search_string is None:
942
+ search_string = '*'
943
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
944
+ if search_string is None:
945
+ search_string = '*'
946
+
947
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
948
+ if output_format is None:
949
+ output_format = "LIST"
950
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
951
+ valid = False
952
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
953
+
954
+ request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
955
+
956
+ if directive == "display":
957
+ print(request_display)
958
+ return None
959
+ elif directive == "validate":
960
+ print(request_display)
961
+ return valid
962
+ elif directive == "process":
963
+ try:
964
+ print(request_display)
965
+ if not valid: # First validate the term before we process it
966
+ return None
967
+
968
+ glossary_list_md = f"\n# Glossary List for `{search_string}`\n\n"
969
+ if output_format == "DICT":
970
+ struct = egeria_client.find_glossaries(search_string, output_format=output_format)
971
+ glossary_list_md += f"```{json.dumps(struct, indent=4)}```\n"
972
+ else:
973
+ glossary_list_md += egeria_client.find_glossaries(search_string, output_format=output_format)
974
+ print_msg("ALWAYS", f"Wrote Glossary List for search string: `{search_string}`", debug_level)
975
+
976
+ return glossary_list_md
977
+
978
+ except Exception as e:
979
+ print(f"{ERROR}Error performing {command}: {e}")
980
+ console.print_exception(show_locals=True)
981
+ return None
982
+ else:
983
+ return None
984
+
985
+
986
+ def process_term_details_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
987
+ """ List terms as a markdown table. Filter based on optional search string. """
988
+ set_debug_level(directive)
989
+ valid = True
990
+ command = extract_command(txt)
991
+ object_type = command.split(' ')[1].strip()
992
+ object_action = command.split(' ')[0].strip()
993
+
994
+ term_identifier = process_simple_attribute(txt, TERM_NAME_LABELS, "ERROR")
995
+
996
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_identifier}` with directive: `{directive}`"))
997
+
998
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
999
+ if output_format is None:
1000
+ output_format = "REPORT"
1001
+ else:
1002
+ output_format = output_format.upper()
1003
+
1004
+ if output_format not in ["DICT", "REPORT"]:
1005
+ valid = False
1006
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1007
+
1008
+ request_display = f"\n\t* Term Identifier: {term_identifier}\n\t* Output Format {output_format}"
1009
+
1010
+ if directive == "display":
1011
+ print(request_display)
1012
+ return None
1013
+ elif directive == "validate":
1014
+ print(request_display)
1015
+ return valid
1016
+ elif directive == "process":
1017
+ try:
1018
+ print(request_display)
1019
+ if not valid: # First validate the term before we process it
1020
+ return None
1021
+ output = egeria_client.get_term_details(term_identifier, output_format=output_format)
1022
+ if output_format == "DICT":
1023
+ output = f"```{json.dumps(output, indent=4)}```"
1024
+ print_msg("ALWAYS", f"Wrote Term Details for term: `{term_identifier}`", debug_level)
1025
+
1026
+ return output
1027
+
1028
+ except Exception as e:
1029
+ print(f"{ERROR}Error performing {command}: {e}")
1030
+ console.print_exception(show_locals=True)
1031
+ return None
1032
+ else:
1033
+ return None
1034
+
1035
+
1036
+ def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1037
+ """ List terms as a markdown table. Filter based on optional search string. """
1038
+ set_debug_level(directive)
1039
+ valid = True
1040
+ command = extract_command(txt)
1041
+ object_type = command.split(' ')[1].strip()
1042
+ object_action = command.split(' ')[0].strip()
1043
+
1044
+ element_labels = TERM_NAME_LABELS
1045
+ element_labels.append('Display Name')
1046
+
1047
+ term_name = process_simple_attribute(txt, element_labels, "ERROR")
1048
+
1049
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1050
+ element_labels, txt, object_action, )
1051
+
1052
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1053
+
1054
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1055
+ if output_format is None:
1056
+ output_format = "LIST"
1057
+ elif output_format not in ["DICT", "LIST"]:
1058
+ valid = False
1059
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1060
+
1061
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format {output_format}\n\t* GUID: {known_guid}\n"
1062
+
1063
+ if directive == "display":
1064
+ print(request_display)
1065
+ return None
1066
+ elif directive == "validate":
1067
+ print(request_display)
1068
+ return valid
1069
+ elif directive == "process":
1070
+ try:
1071
+ print(request_display)
1072
+ if not valid: # First validate the term before we process it
1073
+ return None
1074
+ term_history_md = f"\n# Term History for `{term_name}`\n\n"
1075
+ if output_format == "DICT":
1076
+ struct = egeria_client.list_term_revision_history(known_guid, output_format=output_format)
1077
+ term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
1078
+ else:
1079
+ term_history_md += egeria_client.list_full_term_history(known_guid, output_format)
1080
+ print_msg("ALWAYS", f"Wrote Term History for term `{term_name}`", debug_level)
1081
+
1082
+ return term_history_md
1083
+
1084
+ except Exception as e:
1085
+ print(f"{ERROR}Error performing {command}: {e}")
1086
+ console.print_exception(show_locals=True)
1087
+ return None
1088
+ else:
1089
+ return None
1090
+
1091
+
1092
+ def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
1093
+ str]:
1094
+ """ List term revision history as a markdown table or list."""
1095
+ set_debug_level(directive)
1096
+ valid = True
1097
+ command = extract_command(txt)
1098
+ object_type = command.split(' ')[1].strip()
1099
+ object_action = command.split(' ')[0].strip()
1100
+ known_q_name = None
1101
+ known_guid = None
1102
+
1103
+ element_labels = TERM_NAME_LABELS
1104
+
1105
+ term_name = process_simple_attribute(txt, element_labels, "ERROR")
1106
+ print(Markdown(f"{pre_command} `{command}` for term: `{term_name}` with directive: `{directive}` "))
1107
+
1108
+ known_q_name, known_guid, valid, _ = process_element_identifiers(egeria_client, object_type, element_labels, txt,
1109
+ object_action, )
1110
+ output_format = process_simple_attribute(txt, ['Output Format', 'Format'], 'INFO')
1111
+ if output_format is None:
1112
+ output_format = "LIST"
1113
+ elif output_format not in ["DICT", "LIST", "MD"]:
1114
+ valid = False
1115
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1116
+
1117
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format: {output_format}\n"
1118
+
1119
+ if directive == "display":
1120
+ print(request_display)
1121
+ return None
1122
+ elif directive == "validate":
1123
+ print(request_display)
1124
+ return str(valid)
1125
+ elif directive == "process":
1126
+ try:
1127
+ print(request_display)
1128
+ if not valid: # First validate the term before we process it
1129
+ return None
1130
+ term_history_md = f"\n# Term Revision History for `{term_name}`\n\n"
1131
+ if output_format == "DICT":
1132
+ struct = egeria_client.list_term_revision_history(known_guid, output_format)
1133
+ term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
1134
+ else:
1135
+ term_history_md += egeria_client.list_term_revision_history(known_guid, output_format)
1136
+ print_msg("ALWAYS", f"Wrote Term Revision History for term `{term_name}`", debug_level)
1137
+ return term_history_md
1138
+
1139
+ except Exception as e:
1140
+ print(f"{ERROR}Error performing {command}: {e}")
1141
+ console.print_exception(show_locals=True)
1142
+ return None
1143
+ else:
1144
+ return None