pyegeria 5.3.8.6__py3-none-any.whl → 5.3.8.9__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.
@@ -4,20 +4,19 @@ This file contains functions to parse and process Egeria Markdown (Freddie)
4
4
 
5
5
 
6
6
  """
7
-
7
+ import json
8
8
  import os
9
9
  import re
10
10
  import sys
11
11
  from datetime import datetime
12
- from typing import List, Optional
12
+ from typing import List, Optional, Any
13
13
 
14
14
  from rich import print
15
15
  from rich.console import Console
16
16
  from rich.markdown import Markdown
17
17
 
18
18
  from pyegeria import body_slimmer
19
- from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, \
20
- NO_CATEGORIES_FOUND)
19
+ from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, NO_CATEGORIES_FOUND)
21
20
  from pyegeria.dr_egeria_state import get_element_dictionary, update_element_dictionary, find_key_with_value
22
21
  from pyegeria.egeria_tech_client import EgeriaTech
23
22
  # from pyegeria.md_processing_helpers import process_q_name_list
@@ -27,12 +26,11 @@ EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
27
26
  console = Console(width=EGERIA_WIDTH)
28
27
 
29
28
  command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms",
30
- "List Glossary Terms", "List Term History", "Term Journal Report", "List Glossary Structure",
31
- "List Glossaries", "List Categories", "List Glossary Categories",
32
- "Create Personal Project", "Update Personal Project", "Create Category",
33
- "Update Category", "Create Solution Blueprint", "Update Solution Blueprint",
34
- "Create Solution Component", "Update Solution Component", "Set Parent Category",
35
- "UnSet Parent Category", "Unset Parent Category"]
29
+ "List Glossary Terms", "List Term History", "List Term Revision History", "List Term Update History",
30
+ "List Glossary Structure", "List Glossaries", "List Categories", "List Glossary Categories",
31
+ "Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
32
+ "Create Solution Blueprint", "Update Solution Blueprint", "Create Solution Component",
33
+ "Update Solution Component", ]
36
34
  # verbosity - verbose, quiet, debug
37
35
  debug_level = "debug"
38
36
  message_types = {
@@ -45,12 +43,14 @@ INFO = "INFO"
45
43
  WARNING = "WARNING"
46
44
  pre_command = "\n---\n==> Processing command:"
47
45
  command_seperator = Markdown("\n---\n")
46
+ EXISTS_REQUIRED = "Exists Required"
48
47
 
49
48
  GLOSSARY_NAME_LABELS = ["Glossary Name", "Glossary", "Glossaries", "Owning Glossary", "In Glossary"]
50
49
  CATEGORY_NAME_LABELS = ["Glossary Category Name", "Glossary Category", "Glossary Categories", "Category Name",
51
50
  "Category", "Categories"]
52
51
  PARENT_CATEGORY_LABELS = ["Parent Category Name", "Parent Category", "parent category name", "parent category"]
53
- CHILD_CATEGORY_LABELS = ["Child Category Name", "Child Category", "child category name", "child category"]
52
+ CHILD_CATEGORY_LABELS = ["Child Categories", "Child Category", "child category names", "child categories",
53
+ "Child Category Names"]
54
54
  TERM_NAME_LABELS = ["Glossary Term Name", "Glossary Term", "Glossary Terms", "Term Name", "Term", "Terms", "Term Names"]
55
55
  PROJECT_NAME_LABELS = ["Project Name", "Project", "Project Names", "Projects"]
56
56
  BLUEPRINT_NAME_LABELS = ["Solution Blueprint Name", "Solution Blueprint", "Solution Blueprints", "Blueprint Name",
@@ -64,8 +64,12 @@ SOLUTION_ACTOR_ROLE_LABELS = ["Solution Actor Role Name", "Solution Actor Role N
64
64
  SOLUTION_LINKING_ROLE_LABELS = ["Solution Linking Role Name", "Solution Linking Role Names", "Solution Linking Role",
65
65
  "Solution Linking Roles", "Linking Role Name", "Linking Role", "Linking Roles",
66
66
  "Linking Role Names"]
67
+ OUTPUT_LABELS = ["Output", "Output Format"]
68
+ SEARCH_LABELS = ['Search String', 'Filter']
67
69
  GUID_LABELS = ['GUID', 'guid']
68
70
 
71
+ ELEMENT_OUTPUT_FORMATS = ["LIST", "DICT", "MD", "FORM", "REPORT"]
72
+
69
73
 
70
74
  def render_markdown(markdown_text: str) -> None:
71
75
  """Renders the given markdown text in the console."""
@@ -151,12 +155,13 @@ def update_term_categories(egeria_client: EgeriaTech, term_guid: str, categories
151
155
  egeria_client.remove_term_from_category(term_guid, cat)
152
156
  msg = f"Removed term {term_guid} from category {cat}"
153
157
  print_msg("DEBUG-INFO", msg, debug_level)
154
- else: # No categories specified - so remove any categories a term is in
158
+ else: # No categories specified - so remove any categories a term is in
155
159
  for cat in current_categories:
156
160
  egeria_client.remove_term_from_category(term_guid, cat)
157
161
  msg = f"Removed term {term_guid} from category {cat}"
158
162
  print_msg("DEBUG-INFO", msg, debug_level)
159
163
 
164
+
160
165
  def extract_command_plus(block: str) -> tuple[str, str, str] | None:
161
166
  """
162
167
  Extracts a multi-word object and its associated action from the given block of text.
@@ -219,7 +224,7 @@ def extract_command(block: str) -> str | None:
219
224
  return None
220
225
 
221
226
 
222
- def extract_attribute(text: str, labels: [str]) -> str | None:
227
+ def extract_attribute(text: str, labels: list[str]) -> str | None:
223
228
  """
224
229
  Extracts the attribute value from a string.
225
230
 
@@ -228,7 +233,7 @@ def extract_attribute(text: str, labels: [str]) -> str | None:
228
233
  labels: List of equivalent labels to search for
229
234
 
230
235
  Returns:
231
- The glossary name, or None if not found.
236
+ The value of the attribute, or None if not found.
232
237
 
233
238
  Note:
234
239
  Lines beginning with '>' are ignored.
@@ -251,6 +256,8 @@ def extract_attribute(text: str, labels: [str]) -> str | None:
251
256
  if not extracted_text.isspace() and extracted_text:
252
257
  return extracted_text # Return the cleaned text - I removed the title casing
253
258
 
259
+ return None
260
+
254
261
 
255
262
  def print_msg(msg_level: str, msg: str, verbosity: str):
256
263
  """
@@ -288,7 +295,7 @@ def print_msg(msg_level: str, msg: str, verbosity: str):
288
295
  sys.exit(1)
289
296
 
290
297
 
291
- def process_simple_attribute(txt: str, labels: [str], if_missing: str = INFO) -> str | None:
298
+ def process_simple_attribute(txt: str, labels: list[str], if_missing: str = INFO) -> str | None:
292
299
  """Process a simple attribute based on the provided labels and if_missing value.
293
300
  Extract the attribute value from the text and return it if it exists.
294
301
  If it doesn`t exist, return None and print an error message with severity of if_missing.
@@ -375,14 +382,14 @@ def process_provenance_command(file_path: str, txt: [str]) -> str:
375
382
  return f"\n# Provenance:\n{existing_prov}\n{output}\n"
376
383
 
377
384
 
378
- def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: [str], txt: str,
385
+ def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: list[str], txt: str,
379
386
  action: str, version: str = None) -> tuple[str, str, bool, bool]:
380
387
  """
381
388
  Processes element identifiers by extracting display name and qualified name from the input text,
382
389
  checking if the element exists in Egeria, and validating the information.
383
390
 
384
- Parameters:
385
- element_labels:
391
+ Parameters
392
+ ----------
386
393
  egeria_client: EgeriaTech
387
394
  Client object for interacting with Egeria.
388
395
  element_type: str
@@ -441,7 +448,7 @@ def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, el
441
448
  update_element_dictionary(q_name, {'display_name': element_name})
442
449
  elif qualified_name:
443
450
  update_element_dictionary(qualified_name, {'display_name': element_name})
444
- elif action == "Exists Required":
451
+ elif action == EXISTS_REQUIRED:
445
452
  if not exists:
446
453
  msg = f"Required {element_type} `{element_name}` does not exist"
447
454
  print_msg("DEBUG-ERROR", msg, debug_level)
@@ -528,19 +535,19 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str) ->
528
535
  unique = True
529
536
  return el_qname, el_guid, unique, exists
530
537
 
531
- # Convert element_type to plural form for method name construction # if element_type.endswith('y'): # #
532
- # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{ #
538
+ # Convert element_type to plural form for method name construction # if element_type.endswith('y'): # # #
539
+ # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{ # #
533
540
  # element_type}es" # else: # plural_type = f"{element_type}s" # # # Construct method name # method_name
534
541
  # = f"get_{plural_type}_by_name" # # # Check if the method exists on the client # if hasattr(egeria_client,
535
542
  # method_name): # # Call the method # method = getattr(egeria_client, method_name) # result = #
536
- # method(element_name) # return result # else: # # Method doesn't exist # return f"Method { #
543
+ # method(element_name) # return result # else: # # Method doesn't exist # return f"Method { # #
537
544
  # method_name} not found on client"
538
545
 
539
546
 
540
- def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str, element_labels: [str]) -> tuple[
541
- str | None, list | None, bool, bool]:
547
+ def process_name_list(egeria_client: EgeriaTech, element_type: str, txt: str, element_labels: list[str]) -> tuple[str,
548
+ list[Any], bool | Any, bool | None | Any] | None:
542
549
  """
543
- Processes a list of qualified names specified in the given text, retrieves details for each
550
+ Processes a list of names specified in the given text, retrieves details for each
544
551
  element based on the provided type, and generates a list of valid qualified names.
545
552
 
546
553
  The function reads a text block, extracts a list of element names according to the specified
@@ -552,8 +559,8 @@ def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str,
552
559
 
553
560
  egeria_client (EgeriaTech): The client instance to connect and query elements from an
554
561
  external system.
555
- element_type (str): The type of element, such as schema or attribute, to process.
556
- txt (str): The raw input text containing element names to be processed.
562
+ Element_type (str): The type of element, such as schema or attribute, to process.
563
+ Txt (str): The raw input text containing element names to be processed.
557
564
  element_labels: a list of equivalent label names to use in processing the element.
558
565
 
559
566
  Returns:
@@ -604,8 +611,7 @@ def process_q_name_list(egeria_client: EgeriaTech, element_type: str, txt: str,
604
611
  return elements, new_element_list, valid, exists
605
612
 
606
613
 
607
- def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
608
- directive: str = "display") -> Optional[str]:
614
+ def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
609
615
  """
610
616
  Processes a blueprint create or update command by extracting key attributes such as
611
617
  blueprint name, description, and version from the given cell.
@@ -676,11 +682,11 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
676
682
  print_msg("ALWAYS", msg, debug_level)
677
683
 
678
684
  # update with get blueprint by guid
679
- return 'Would return get blueprint by guid and return md' # egeria_client.get_term_by_guid( #
685
+ return 'Would return get blueprint by guid and return md' # egeria_client.get_term_by_guid( # #
680
686
  # known_guid, 'md')
681
687
 
682
688
  elif object_action == "Update" and directive == "validate":
683
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( #
689
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # #
684
690
  # known_guid, 'md')
685
691
 
686
692
  elif object_action == "Create":
@@ -709,8 +715,8 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
709
715
  return None
710
716
 
711
717
 
712
- def process_solution_component_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
713
- directive: str = "display") -> Optional[str]:
718
+ def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
719
+ Optional[str]:
714
720
  """
715
721
  Processes a solution componentt create or update command by extracting key attributes such as
716
722
  solution component name, description, version, solution component type etc from the given cell.
@@ -756,9 +762,8 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
756
762
  if solution_blueprints: # Find information about blueprints that include this component
757
763
  msg = "Checking for blueprints that include this solution component"
758
764
  print_msg("DEBUG-INFO", msg, debug_level)
759
- solution_blueprints, bp_qname_list, bp_valid, bp_exist = process_q_name_list(egeria_client,
760
- 'Solution Blueprints', txt,
761
- BLUEPRINT_NAME_LABELS)
765
+ solution_blueprints, bp_qname_list, bp_valid, bp_exist = process_name_list(egeria_client, 'Solution Blueprints',
766
+ txt, BLUEPRINT_NAME_LABELS)
762
767
  if bp_exist and bp_valid:
763
768
  msg = f"Found valid blueprints that include this solution component:\n\t{solution_blueprints}"
764
769
  print_msg("INFO", msg, debug_level)
@@ -769,8 +774,8 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
769
774
  msg = f"Parent Components are missing"
770
775
  print_msg("INFO", msg, debug_level)
771
776
  else:
772
- parent_components, parent_qname_list, parents_valid, parent_components_exist = process_q_name_list(
773
- egeria_client, 'Parent Components', txt, COMPONENT_NAME_LABELS)
777
+ parent_components, parent_qname_list, parents_valid, parent_components_exist = process_name_list(egeria_client,
778
+ 'Parent Components', txt, COMPONENT_NAME_LABELS)
774
779
  if parent_components_exist and parents_valid:
775
780
  msg = f"Found valid parent components that include this solution component:\n\t{parent_qname_list}"
776
781
  print_msg("INFO", msg, debug_level)
@@ -843,11 +848,11 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
843
848
  msg = f"\nUpdated Solution Component `{display_name}` with GUID {known_guid}"
844
849
  print_msg("ALWAYS", msg, debug_level)
845
850
  # update with get solution component by guid
846
- return 'Would return get Solution Component by guid and return md' # #
851
+ return 'Would return get Solution Component by guid and return md' # # #
847
852
  # egeria_client.get_term_by_guid(known_guid, 'md')
848
853
 
849
854
  elif object_action == "Update" and directive == "validate":
850
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( #
855
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # #
851
856
  # known_guid, 'md')
852
857
 
853
858
  elif object_action == "Create":
@@ -865,7 +870,7 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
865
870
  msg = f"\nCreated Solution Component `{display_name}` with GUID {known_guid}"
866
871
  print_msg("ALWAYS", msg, debug_level)
867
872
  update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
868
- return 'Would return get solution component by guid results as md' # #
873
+ return 'Would return get solution component by guid results as md' # # #
869
874
  # egeria_client.get_term_by_guid(term_guid, 'MD')
870
875
 
871
876
  except Exception as e:
@@ -875,8 +880,7 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
875
880
  return None
876
881
 
877
882
 
878
- def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
879
- directive: str = "display") -> Optional[str]:
883
+ def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
880
884
  """
881
885
  Processes a glossary create or update command by extracting key attributes such as
882
886
  glossary name, language, description, and usage from the given text.
@@ -886,13 +890,11 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
886
890
  :param directive: an optional string indicating the directive to be used - display, validate or execute
887
891
  :return: A string summarizing the outcome of the processing.
888
892
  """
889
- # command = extract_command(txt)
890
- # object_type = command.split(' ')[1].strip()
891
- # object_action = command.split(' ')[0].strip()
893
+
892
894
  command, object_type, object_action = extract_command_plus(txt)
893
895
  set_debug_level(directive)
894
896
 
895
- glossary_name = process_simple_attribute(txt, ['Glossary Name', 'Display Name'])
897
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS)
896
898
  print(Markdown(
897
899
  f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `"
898
900
  f"{directive}` "))
@@ -903,7 +905,9 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
903
905
 
904
906
  if glossary_name is None:
905
907
  valid = False
906
- known_q_name, known_guid, glossary_exists = None
908
+ known_q_name = None
909
+ known_guid = None
910
+ glossary_exists = False
907
911
  else:
908
912
  element_labels = GLOSSARY_NAME_LABELS
909
913
  element_labels.append('Display Name')
@@ -960,9 +964,8 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
960
964
 
961
965
  if object_action == "Update":
962
966
  if not glossary_exists:
963
- print(
964
- f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
965
- f"command\n")
967
+ print(f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
968
+ f"command\n")
966
969
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
967
970
 
968
971
  body = {
@@ -996,10 +999,13 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
996
999
  # return update_a_command(txt, command, object_type, qualified_name, glossary_guid)
997
1000
  print_msg(ALWAYS, f"Created Glossary `{glossary_name}` with GUID {glossary_guid}", debug_level)
998
1001
  return egeria_client.get_glossary_by_guid(glossary_guid, output_format='MD')
1002
+ else:
1003
+ return None
1004
+ else:
1005
+ return None
999
1006
 
1000
1007
 
1001
- def process_categories_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1002
- directive: str = "display") -> Optional[str]:
1008
+ def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1003
1009
  """
1004
1010
  Processes a glossary category create or update command by extracting key attributes such as
1005
1011
  category name, qualified, description, and anchor glossary from the given txt..
@@ -1011,9 +1017,7 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1011
1017
  """
1012
1018
  valid = True
1013
1019
  set_debug_level(directive)
1014
- # command = extract_command(txt)
1015
- # object_type = command.split(' ')[1].strip()
1016
- # object_action = command.split(' ')[0].strip()
1020
+
1017
1021
  command, object_type, object_action = extract_command_plus(txt)
1018
1022
 
1019
1023
  category_name = process_simple_attribute(txt, ['Category Name', 'category_name', 'Cat'])
@@ -1023,6 +1027,8 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1023
1027
  description = process_simple_attribute(txt, ['Description'])
1024
1028
  q_name = process_simple_attribute(txt, ['Qualified Name'])
1025
1029
 
1030
+ parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS, "INFO")
1031
+
1026
1032
  element_labels = CATEGORY_NAME_LABELS
1027
1033
  element_labels.append('Display Name')
1028
1034
  # Check if category exists (and get qname and guid)
@@ -1040,17 +1046,27 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1040
1046
  if owning_glossary_name is None:
1041
1047
  valid = False
1042
1048
  known_glossary_q_name, known_glossary__guid, glossary_exists = None
1049
+
1043
1050
  else:
1044
1051
  known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(
1045
- egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, "Exists Required", None)
1052
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
1053
+
1054
+ if parent_category_name:
1055
+ _, parent_guid, parent_valid, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1056
+ parent_category_name)
1057
+ else:
1058
+ parent_guid = None
1059
+ parent_exists = False
1060
+ parent_valid = False
1046
1061
 
1047
1062
  category_display = (
1048
1063
  f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_name}\n\t"
1049
- f"* Description:\n{description}\n\t* Qualified Name: {q_name}\n\t")
1064
+ f"* Description:\n{description}\n\t* Parent Category: {parent_category_name}\n\t"
1065
+ f"* Qualified Name: {q_name}\n\t")
1050
1066
 
1051
1067
  if object_action == 'Update':
1052
1068
  guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
1053
- # update_description = process_simple_attribute(txt, 'Update Description')
1069
+
1054
1070
  category_display += (f"* GUID: {guid}\n\n")
1055
1071
  if not category_exists:
1056
1072
  msg = f"Category {category_name} can't be updated; {category_name} not found."
@@ -1097,14 +1113,22 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1097
1113
  f"command\n")
1098
1114
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
1099
1115
 
1116
+ # Update the basic category properties
1100
1117
  egeria_client.update_category(known_guid, category_name, description, known_q_name, None)
1101
1118
  msg = f"->Updated category `{category_name}`with GUID {known_guid}"
1102
1119
  print_msg(ALWAYS, msg, debug_level)
1120
+
1121
+ # Update parent-child relationships
1122
+
1103
1123
  update_element_dictionary(known_q_name, {
1104
1124
  'guid': known_guid, 'display_name': category_name
1105
1125
  })
1106
1126
  print_msg(ALWAYS, f"Updated Category `{category_name}` with GUID {known_guid}", debug_level)
1107
- return egeria_client.get_categories_by_guid(known_guid, output_format='FORM')
1127
+
1128
+ category_sync = update_category_parent(egeria_client, known_guid, parent_category_name)
1129
+ print_msg(ALWAYS, f"Updated Category hierarchy for `{category_name}` with outcome {category_sync}",
1130
+ debug_level)
1131
+ return egeria_client.get_category_by_guid(known_guid, output_format='FORM')
1108
1132
 
1109
1133
  elif object_action == "Create":
1110
1134
  is_root = True
@@ -1116,7 +1140,7 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1116
1140
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
1117
1141
  else:
1118
1142
  category_guid = egeria_client.create_category(known_glossary_guid, category_name, description, is_root)
1119
- category_details = egeria_client.get_categories_by_guid(category_guid)
1143
+ category_details = egeria_client.get_category_by_guid(category_guid)
1120
1144
 
1121
1145
  if category_details == NO_CATEGORIES_FOUND:
1122
1146
  msg = f"Just created category with GUID {category_guid} but category not found"
@@ -1128,151 +1152,129 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1128
1152
  'guid': category_guid, 'display_name': category_name
1129
1153
  })
1130
1154
  print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
1131
- return egeria_client.get_categories_by_guid(category_guid, output_format='DR')
1132
-
1155
+ if parent_valid & parent_exists:
1156
+ egeria_client.set_parent_category(parent_guid, category_guid)
1157
+ print_msg(ALWAYS, f"Set parent category for `{category_name}` to `{parent_category_name}`",
1158
+ debug_level)
1159
+ else:
1160
+ print_msg(ERROR,
1161
+ f"Parent category `{parent_category_name}` not found or invalid for `{category_name}`",
1162
+ debug_level)
1163
+ return egeria_client.get_category_by_guid(category_guid, output_format='FORM')
1164
+ return None
1165
+ return None
1133
1166
 
1134
- def process_set_categories_parent_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1135
- directive: str = "display") -> Optional[str]:
1136
- """
1137
- Processes a set_parent_category command by extracting key attributes such as
1138
- parent and child category names from the given text.
1139
1167
 
1140
- :param txt: A string representing the input cell to be processed for
1141
- extracting category-related attributes.
1142
- :param directive: an optional string indicating the directive to be used - display, validate or execute
1143
- :return: A string summarizing the outcome of the processing.
1168
+ def update_category_parent(egeria_client, category_guid: str, parent_category_name: str = None) -> bool:
1144
1169
  """
1145
- valid = True
1146
- set_debug_level(directive)
1170
+ Updates the parent relationship for a category.
1147
1171
 
1148
- command, object_type, object_action = extract_command_plus(txt)
1172
+ If a parent category is specified, it will check if a parent is currently set.
1173
+ If a parent category was set and is the same as the parent category specified, no change is needed.
1174
+ If a parent category was set and is different from the parent_category_name, the parent category is updated.
1175
+ If parent_category_name is None or empty and an existing parent category was set, the parent category is removed.
1149
1176
 
1150
- parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS, "ERROR")
1151
- child_category_name = process_simple_attribute(txt, CHILD_CATEGORY_LABELS, "ERROR")
1152
- print(Markdown(f"{pre_command} `{command}` for parent category: `\'{parent_category_name}\'` \n\t"
1153
- f"and child category: `\'{child_category_name}\'` \nwith directive: `{directive}` "))
1177
+ Parameters
1178
+ ----------
1179
+ egeria_client: EgeriaTech
1180
+ The Egeria client to use for API calls
1181
+ category_guid: str
1182
+ The GUID of the category to update
1183
+ parent_category_name: str, optional
1184
+ The name of the parent category to set, or None to remove the parent
1154
1185
 
1155
- if parent_category_name is None or child_category_name is None:
1156
- valid = False
1157
- else:
1158
- parent_cat_q_name, parent_cat_guid, parent_cat_valid, parent_cat_exists = (
1159
- get_element_by_name(egeria_client, 'Glossary Categories', parent_category_name))
1160
- child_cat_q_name, child_cat_guid, child_cat_valid, child_cat_exists = (
1161
- get_element_by_name(egeria_client, 'Glossary Categories', child_category_name))
1186
+ Returns
1187
+ -------
1162
1188
 
1163
- # Check if category exists (and get qname and guid)
1189
+ True if successful, False otherwise.
1164
1190
 
1165
- if parent_cat_exists and child_cat_exists:
1166
- valid = True
1167
- msg = f" Both categories {parent_category_name} and {child_category_name} exist\n"
1168
- print_msg(INFO, msg, debug_level)
1169
- if parent_cat_guid and child_cat_guid:
1170
- msg = f" Both categories {parent_category_name} and {child_category_name} have GUIDs\n"
1171
- print_msg(INFO, msg, debug_level)
1191
+ """
1192
+ outcome = True
1193
+ # Handle parent category updates
1194
+ if parent_category_name:
1195
+ # Check if a parent is currently set
1196
+ current_parent = egeria_client.get_category_parent(category_guid)
1197
+
1198
+ if isinstance(current_parent, str) and "No Parent Category found" in current_parent:
1199
+ # No parent currently set, need to set it
1200
+ _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1201
+ parent_category_name)
1202
+
1203
+ if parent_exists and parent_guid:
1204
+ egeria_client.set_parent_category(parent_guid, category_guid)
1205
+ print_msg(ALWAYS, f"Set parent category of category to `{parent_category_name}`", debug_level)
1206
+ else:
1207
+ print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
1208
+ outcome = False
1172
1209
  else:
1173
- msg = f" Both categories {parent_category_name} and {child_category_name} do not have GUIDs\n"
1174
- print_msg(ERROR, msg, debug_level)
1175
- valid = False
1210
+ # Parent is set, check if it's the same
1211
+ current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
1212
+
1213
+ if current_parent_name != parent_category_name:
1214
+ # Different parent, need to update
1215
+ # First remove the current parent
1216
+ current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
1217
+ if current_parent_guid:
1218
+ egeria_client.remove_parent_category(current_parent_guid, category_guid)
1219
+
1220
+ # Then set the new parent
1221
+ _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1222
+ parent_category_name)
1223
+
1224
+ if parent_exists and parent_guid:
1225
+ egeria_client.set_parent_category(parent_guid, category_guid)
1226
+ print_msg(ALWAYS,
1227
+ f"Updated parent category from `{current_parent_name}` to `{parent_category_name}`",
1228
+ debug_level)
1229
+ else:
1230
+ print_msg(ERROR, f"Parent category `{parent_category_name}` not found", debug_level)
1231
+ outcome = False
1232
+ elif parent_category_name is None or parent_category_name == '':
1233
+ # Check if a parent is currently set and remove it if needed
1234
+ current_parent = egeria_client.get_category_parent(category_guid)
1176
1235
 
1236
+ if not isinstance(current_parent, str) or "No Parent Category found" not in current_parent:
1237
+ # Parent is set, need to remove it
1238
+ current_parent_guid = current_parent.get('elementHeader', {}).get('guid', '')
1239
+ current_parent_name = current_parent.get('glossaryCategoryProperties', {}).get('qualifiedName', '')
1177
1240
 
1178
- else:
1179
- valid = False
1180
- msg = f"Both categories {parent_category_name} and {child_category_name} do NOT exist\n"
1181
- print_msg(ERROR, msg, debug_level)
1182
-
1183
- category_display = (f"\n* Command: {command}\n\t* Parent Category: {parent_category_name}\n\t\t"
1184
- f"* Qualified Name: {parent_cat_q_name}\n\t\t* GUID: {parent_cat_guid}\n\t"
1185
- f"* Child Category:\n{child_category_name}\n\t\t* Qualified Name: {child_cat_q_name}\n\t\t"
1186
- f"* GUID: {child_cat_guid}\n")
1187
-
1188
- # if object_action == 'Remove Parent Category':
1189
- # parent_guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
1190
- #
1191
- # category_display += (f"* GUID: {guid}\n\n")
1192
- # if not category_exists:
1193
- # msg = f"Category {category_name} can't be updated; {category_name} not found."
1194
- # print_msg(ERROR, msg, debug_level)
1195
- # valid = False
1196
- # else:
1197
- # msg = f"Glossary can be updated; {category_name} found"
1198
- # print_msg(ALWAYS, msg, debug_level)
1199
- #
1200
- # elif object_action == "Create":
1201
- # if category_exists:
1202
- # msg = f"Category {category_name} can't be created because it already exists.\n"
1203
- # print_msg("ERROR", msg, debug_level)
1204
- # valid = False
1205
- # elif valid:
1206
- # msg = f"It is valid to create Category `{category_name}` with:\n"
1207
- # print_msg("ALWAYS", msg, debug_level)
1241
+ if current_parent_guid:
1242
+ egeria_client.remove_parent_category(current_parent_guid, category_guid)
1243
+ print_msg(ALWAYS, f"Removed parent category `{current_parent_name}`", debug_level)
1208
1244
 
1209
- if directive == "display":
1210
- print(Markdown(category_display))
1211
- return None
1245
+ return outcome
1212
1246
 
1213
- elif directive == "validate":
1214
- if valid:
1215
- print(Markdown(category_display))
1216
- else:
1217
- msg = f"Validation failed for {object_type} `{parent_category_name}`\n"
1218
- print_msg(ERROR, msg, debug_level)
1219
- print(Markdown(category_display))
1220
- return valid
1221
1247
 
1222
- elif directive == "process":
1223
- if valid:
1224
- print(Markdown(category_display))
1225
- else:
1226
- msg = f"* --> Validation failed for {object_type} `{parent_category_name}`\n"
1227
- print_msg(ERROR, msg, debug_level)
1228
- print(Markdown(category_display))
1229
- return None
1230
-
1231
- if object_action in ["Set", "Set Parent"]:
1232
- egeria_client.set_parent_category(parent_cat_guid, child_cat_guid)
1233
- print_msg(ALWAYS, f"Set parent category of `{child_category_name}` to `{parent_category_name}`",
1234
- debug_level)
1235
- output_txt = txt.replace("Set Parent", "UnSet Parent")
1236
- return output_txt
1237
-
1238
- elif object_action in ["UnSet", "UnSet Parent", "Unset Parent", "Unset", "Remove Parent"]:
1239
- egeria_client.remove_parent_category(parent_cat_guid, child_cat_guid)
1240
- print_msg(ALWAYS, f"UnSet parent category `{child_category_name}` from {parent_category_name}", debug_level)
1241
- output_txt = txt.replace("UnSet Parent", "Set Parent")
1242
- return output_txt
1243
-
1244
- def process_term_list_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1245
- directive: str = "display") -> Optional[str]:
1248
+ def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1246
1249
  """ List terms as a markdown table. Filter based on optional search string. """
1247
1250
  set_debug_level(directive)
1248
1251
  valid = True
1249
1252
  command = extract_command(txt)
1250
- object_type = command.split(' ')[1].strip()
1251
- object_action = command.split(' ')[0].strip()
1252
- known_glossary_q = ""
1253
- known_glossary_guid = ""
1254
- glossary_exists = False
1255
- glossary_valid = False
1256
-
1257
1253
 
1258
- search_string = process_simple_attribute(txt, ['Search String', 'Filter'])
1254
+ search_string = process_simple_attribute(txt, SEARCH_LABELS)
1259
1255
  if search_string is None:
1260
1256
  search_string = '*'
1261
1257
  print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1262
1258
 
1263
1259
  glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1264
1260
  if glossary is not None:
1265
- _, glossary_guid, _, glossary_exists = get_element_by_name(
1266
- egeria_client, "Glossary", glossary)
1261
+ _, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
1267
1262
  msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
1268
1263
  print_msg(INFO, msg, debug_level)
1269
1264
  else:
1270
- glossary_guid= None
1265
+ glossary_guid = None
1271
1266
  msg = f"No glossary found"
1272
1267
  print_msg(INFO, msg, debug_level)
1273
1268
 
1269
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS)
1270
+ if output_format is None:
1271
+ output_format = "LIST"
1272
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
1273
+ valid = False
1274
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1274
1275
 
1275
- request_display = f"\n* Search String: {search_string}\n* Glossary: {glossary}\n"
1276
+ request_display = (f"\n\t* Search String: {search_string}\n\t* Glossary: {glossary}\n\t* Output Format: "
1277
+ f"{output_format}\n")
1276
1278
 
1277
1279
  if directive == "display":
1278
1280
  print(Markdown(request_display))
@@ -1286,47 +1288,49 @@ def process_term_list_command(egeria_client: EgeriaTech, element_dictionary: dic
1286
1288
  if not valid: # First validate the term before we process it
1287
1289
  return None
1288
1290
 
1289
- md_table = egeria_client.find_glossary_terms(search_string,glossary_guid, output_format = "LIST")
1291
+ term_list_md = f"\n# Term List for search string: `{search_string}`\n\n"
1292
+ if output_format == "DICT":
1293
+ struct = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
1294
+ term_list_md += f"{json.dumps(struct, indent=4)}\n"
1295
+ else:
1296
+ term_list_md += egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
1297
+ print_msg("ALWAYS", f"Wrote Term List for search string: `{search_string}`", debug_level)
1290
1298
 
1299
+ return term_list_md
1300
+
1301
+
1302
+ md_table = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
1303
+
1304
+ print_msg("ALWAYS", f"Wrote Term list for search string `{search_string}`", debug_level)
1291
1305
  return md_table
1292
1306
 
1293
1307
  except Exception as e:
1294
- print(f"{ERROR}Error creating Glossary Term list: {e}")
1308
+ print(f"{ERROR}Error performing {command}: {e}")
1295
1309
  console.print_exception(show_locals=True)
1296
1310
  return None
1311
+ else:
1312
+ return None
1297
1313
 
1298
- def process_category_list_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1299
- directive: str = "display") -> Optional[str]:
1314
+
1315
+ def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1300
1316
  """ List terms as a markdown table. Filter based on optional search string. """
1301
1317
  set_debug_level(directive)
1302
1318
  valid = True
1303
1319
  command = extract_command(txt)
1304
- object_type = command.split(' ')[1].strip()
1305
- object_action = command.split(' ')[0].strip()
1306
- known_glossary_q = ""
1307
- known_glossary_guid = ""
1308
- glossary_exists = False
1309
- glossary_valid = False
1310
-
1311
1320
 
1312
- search_string = process_simple_attribute(txt, ['Search String', 'Filter'])
1321
+ search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
1313
1322
  if search_string is None:
1314
1323
  search_string = '*'
1315
1324
  print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1316
1325
 
1317
- # glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1318
- # if glossary is not None:
1319
- # _, glossary_guid, _, glossary_exists = get_element_by_name(
1320
- # egeria_client, "Glossary", glossary)
1321
- # msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
1322
- # print_msg(INFO, msg, debug_level)
1323
- # else:
1324
- # glossary_guid= None
1325
- # msg = f"No glossary found"
1326
- # print_msg(INFO, msg, debug_level)
1327
-
1326
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1327
+ if output_format is None:
1328
+ output_format = "LIST"
1329
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
1330
+ valid = False
1331
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1328
1332
 
1329
- request_display = f"\n* Search String: {search_string}\n"
1333
+ request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
1330
1334
 
1331
1335
  if directive == "display":
1332
1336
  print(Markdown(request_display))
@@ -1339,36 +1343,102 @@ def process_category_list_command(egeria_client: EgeriaTech, element_dictionary:
1339
1343
  print(Markdown(request_display))
1340
1344
  if not valid: # First validate the term before we process it
1341
1345
  return None
1342
- md_table = egeria_client.find_glossary_categories(search_string, output_format = "LIST")
1343
1346
 
1344
- return md_table
1347
+ cat_list_md = f"\n# Category List for search string: `{search_string}`\n\n"
1348
+ if output_format == "DICT":
1349
+ struct = egeria_client.find_glossary_categories(search_string, output_format=output_format)
1350
+ cat_list_md += f"{json.dumps(struct, indent=4)}\n"
1351
+ else:
1352
+ cat_list_md += egeria_client.find_glossary_categories(search_string, output_format=output_format)
1353
+ print_msg("ALWAYS", f"Wrote Category List for search string: `{search_string}`", debug_level)
1354
+
1355
+ return cat_list_md
1345
1356
 
1346
1357
  except Exception as e:
1347
- print(f"{ERROR}Error creating Glossary Category list: {e}")
1358
+ print(f"{ERROR}Error performing {command}: {e}")
1348
1359
  console.print_exception(show_locals=True)
1349
1360
  return None
1361
+ else:
1350
1362
 
1351
- def process_glossary_list_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1352
- directive: str = "display") -> Optional[str]:
1363
+ return None
1364
+
1365
+
1366
+ def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
1367
+ str]:
1353
1368
  """ List terms as a markdown table. Filter based on optional search string. """
1354
1369
  set_debug_level(directive)
1355
1370
  valid = True
1356
1371
  command = extract_command(txt)
1357
- object_type = command.split(' ')[1].strip()
1358
- object_action = command.split(' ')[0].strip()
1359
- known_glossary_q = ""
1372
+
1360
1373
  known_glossary_guid = ""
1361
- glossary_exists = False
1362
- glossary_valid = False
1363
1374
 
1375
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, "ERROR")
1376
+
1377
+ _, known_glossary_guid, valid, _ = process_element_identifiers(egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt,
1378
+ EXISTS_REQUIRED, None)
1379
+
1380
+ print(Markdown(f"{pre_command} `{command}` for glossary:`{glossary_name}` with directive: `{directive}`"))
1381
+
1382
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1383
+ if output_format is None:
1384
+ output_format = "MD"
1385
+ elif output_format not in ["DICT", "LIST", "MD"]:
1386
+ valid = False
1387
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1388
+
1389
+ request_display = f"\n\t* Glossary name: {glossary_name}\n\t* Output Format: {output_format}\n"
1390
+
1391
+ if directive == "display":
1392
+ print(Markdown(request_display))
1393
+ return None
1394
+ elif directive == "validate":
1395
+ print(Markdown(request_display))
1396
+ return str(valid)
1397
+ elif directive == "process":
1398
+ try:
1399
+ print(Markdown(request_display))
1400
+ if not valid: # First validate the term before we process it
1401
+ return None
1402
+
1403
+ glossary_structure_md = f"\n# Glossary Structure for `{glossary_name}`\n\n"
1404
+ if output_format == "DICT":
1405
+ struct = egeria_client.get_glossary_category_structure(known_glossary_guid, output_format=output_format)
1406
+ glossary_structure_md += f"{json.dumps(struct, indent=4)}\n"
1407
+ else:
1408
+ glossary_structure_md += egeria_client.get_glossary_category_structure(known_glossary_guid, output_format=output_format)
1409
+ print_msg("ALWAYS", f"Wrote Glossary Structure for glossary: `{glossary_name}`", debug_level)
1410
+
1411
+ return glossary_structure_md
1412
+
1413
+ except Exception as e:
1414
+ print(f"{ERROR}Error performing {command}: {e}")
1415
+ console.print_exception(show_locals=True)
1416
+ return None
1417
+ else:
1418
+ return None
1419
+
1420
+
1421
+ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1422
+ """ List terms as a markdown table. Filter based on optional search string. """
1423
+ set_debug_level(directive)
1424
+ valid = True
1425
+ command = extract_command(txt)
1364
1426
 
1365
- search_string = process_simple_attribute(txt, ['Search String', 'Filter'])
1427
+ search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
1366
1428
  if search_string is None:
1367
1429
  search_string = '*'
1368
1430
  print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1431
+ if search_string is None:
1432
+ search_string = '*'
1369
1433
 
1434
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1435
+ if output_format is None:
1436
+ output_format = "LIST"
1437
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
1438
+ valid = False
1439
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1370
1440
 
1371
- request_display = f"\n* Search String: {search_string}\n"
1441
+ request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
1372
1442
 
1373
1443
  if directive == "display":
1374
1444
  print(request_display)
@@ -1382,17 +1452,25 @@ def process_glossary_list_command(egeria_client: EgeriaTech, element_dictionary:
1382
1452
  if not valid: # First validate the term before we process it
1383
1453
  return None
1384
1454
 
1385
- md_table = egeria_client.find_glossaries(search_string, output_format = "LIST")
1455
+ glossary_list_md = f"\n# Glossary List for `{search_string}`\n\n"
1456
+ if output_format == "DICT":
1457
+ struct = egeria_client.find_glossaries(search_string, output_format=output_format)
1458
+ glossary_list_md += f"{json.dumps(struct, indent=4)}\n"
1459
+ else:
1460
+ glossary_list_md += egeria_client.find_glossaries(search_string, output_format=output_format)
1461
+ print_msg("ALWAYS", f"Wrote Glossary List for search string: `{search_string}`", debug_level)
1386
1462
 
1387
- return md_table
1463
+ return glossary_list_md
1388
1464
 
1389
1465
  except Exception as e:
1390
- print(f"{ERROR}Error creating Glossary list: {e}")
1466
+ print(f"{ERROR}Error performing {command}: {e}")
1391
1467
  console.print_exception(show_locals=True)
1392
1468
  return None
1469
+ else:
1470
+ return None
1471
+
1393
1472
 
1394
- def process_term_history_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1395
- directive: str = "display") -> Optional[str]:
1473
+ def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1396
1474
  """ List terms as a markdown table. Filter based on optional search string. """
1397
1475
  set_debug_level(directive)
1398
1476
  valid = True
@@ -1404,16 +1482,20 @@ def process_term_history_command(egeria_client: EgeriaTech, element_dictionary:
1404
1482
  element_labels.append('Display Name')
1405
1483
 
1406
1484
  term_name = process_simple_attribute(txt, element_labels, "ERROR")
1407
- print(Markdown(f"{pre_command} `{command}` for term: `\'{term_name}\'` with directive: `{directive}` "))
1408
1485
 
1409
1486
  known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1410
- element_labels, txt, object_action,
1411
- )
1487
+ element_labels, txt, object_action, )
1412
1488
 
1413
1489
  print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1414
1490
 
1491
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1492
+ if output_format is None:
1493
+ output_format = "LIST"
1494
+ elif output_format not in ["DICT", "LIST"]:
1495
+ valid = False
1496
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1415
1497
 
1416
- request_display = f"\n\t* Term Name: {term_name}\n\t* Qualified Name: {known_q_name}\n\t* GUID: {known_guid}\n"
1498
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format {output_format}\n\t* GUID: {known_guid}\n"
1417
1499
 
1418
1500
  if directive == "display":
1419
1501
  print(request_display)
@@ -1427,20 +1509,79 @@ def process_term_history_command(egeria_client: EgeriaTech, element_dictionary:
1427
1509
  if not valid: # First validate the term before we process it
1428
1510
  return None
1429
1511
  term_history_md = f"\n# Term History for `{term_name}`\n\n"
1430
- term_history_md += egeria_client.list_full_term_history(known_guid, 'LIST')
1512
+ if output_format == "DICT":
1513
+ struct = egeria_client.list_term_revision_history(known_guid, output_format=output_format)
1514
+ term_history_md += f"{json.dumps(struct, indent=4)}\n"
1515
+ else:
1516
+ term_history_md += egeria_client.list_full_term_history(known_guid, output_format)
1517
+ print_msg("ALWAYS", f"Wrote Term History for term `{term_name}`", debug_level)
1431
1518
 
1432
1519
  return term_history_md
1433
1520
 
1434
1521
  except Exception as e:
1435
- print(f"{ERROR}Error creating Glossary list: {e}")
1522
+ print(f"{ERROR}Error performing {command}: {e}")
1436
1523
  console.print_exception(show_locals=True)
1437
1524
  return None
1525
+ else:
1526
+ return None
1438
1527
 
1439
1528
 
1529
+ def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
1530
+ str]:
1531
+ """ List term revision history as a markdown table or list."""
1532
+ set_debug_level(directive)
1533
+ valid = True
1534
+ command = extract_command(txt)
1535
+ object_type = command.split(' ')[1].strip()
1536
+ object_action = command.split(' ')[0].strip()
1537
+ known_q_name = None
1538
+ known_guid = None
1539
+
1540
+ element_labels = TERM_NAME_LABELS
1541
+
1542
+ term_name = process_simple_attribute(txt, element_labels, "ERROR")
1543
+ print(Markdown(f"{pre_command} `{command}` for term: `{term_name}` with directive: `{directive}` "))
1544
+
1545
+ known_q_name, known_guid, valid, _ = process_element_identifiers(egeria_client, object_type, element_labels, txt,
1546
+ object_action, )
1547
+ output_format = process_simple_attribute(txt, ['Output Format', 'Format'], 'INFO')
1548
+ if output_format is None:
1549
+ output_format = "LIST"
1550
+ elif output_format not in ["DICT", "LIST", "MD"]:
1551
+ valid = False
1552
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1553
+
1554
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format: {output_format}\n"
1555
+
1556
+ if directive == "display":
1557
+ print(request_display)
1558
+ return None
1559
+ elif directive == "validate":
1560
+ print(request_display)
1561
+ return str(valid)
1562
+ elif directive == "process":
1563
+ try:
1564
+ print(request_display)
1565
+ if not valid: # First validate the term before we process it
1566
+ return None
1567
+ term_history_md = f"\n# Term Revision History for `{term_name}`\n\n"
1568
+ if output_format == "DICT":
1569
+ struct = egeria_client.list_term_revision_history(known_guid, output_format)
1570
+ term_history_md += f"{json.dumps(struct, indent=4)}\n"
1571
+ else:
1572
+ term_history_md += egeria_client.list_term_revision_history(known_guid, output_format)
1573
+ print_msg("ALWAYS", f"Wrote Term Revision History for term `{term_name}`", debug_level)
1574
+ return term_history_md
1575
+
1576
+ except Exception as e:
1577
+ print(f"{ERROR}Error performing {command}: {e}")
1578
+ console.print_exception(show_locals=True)
1579
+ return None
1580
+ else:
1581
+ return None
1440
1582
 
1441
1583
 
1442
- def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1443
- directive: str = "display") -> Optional[str]:
1584
+ def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1444
1585
  """
1445
1586
  Processes a term create or update command by extracting key attributes such as
1446
1587
  term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
@@ -1492,16 +1633,15 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1492
1633
  glossary_exists = False
1493
1634
  else:
1494
1635
  known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
1495
- egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, "Exists Required", None)
1636
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
1496
1637
 
1497
1638
  # process categories, if present
1498
1639
  categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
1499
1640
  if categories: # Find information about categoriess that classify this term
1500
1641
  msg = "Checking for categories that classify this term"
1501
1642
  print_msg("DEBUG-INFO", msg, debug_level)
1502
- categories_list, cat_q_name_list, cat_valid, cat_exist = process_q_name_list(egeria_client,
1503
- 'Glossary Categories', txt,
1504
- CATEGORY_NAME_LABELS)
1643
+ categories_list, cat_q_name_list, cat_valid, cat_exist = process_name_list(egeria_client, 'Glossary Categories',
1644
+ txt, CATEGORY_NAME_LABELS)
1505
1645
  if cat_exist and cat_valid:
1506
1646
  msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
1507
1647
  print_msg("INFO", msg, debug_level)
@@ -1567,7 +1707,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1567
1707
  f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
1568
1708
  debug_level)
1569
1709
  return egeria_client.get_term_by_guid(known_guid,
1570
- 'md') # return update_a_command(txt, command, object_type,
1710
+ 'md') # return update_a_command(txt, command, object_type,
1571
1711
  # known_q_name, known_guid)
1572
1712
  elif object_action == "Update" and directive == "validate": # is sthis reachable?
1573
1713
  return egeria_client.get_term_by_guid(known_guid, 'md')
@@ -1614,7 +1754,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1614
1754
  update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
1615
1755
  print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
1616
1756
  return egeria_client.get_term_by_guid(term_guid,
1617
- 'MD') # return update_a_command(txt, command,
1757
+ 'MD') # return update_a_command(txt, command,
1618
1758
  # object_type, q_name, term_guid)
1619
1759
  except Exception as e:
1620
1760
  print(f"{ERROR}Error creating term {term_name}: {e}")
@@ -1622,8 +1762,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1622
1762
  return None
1623
1763
 
1624
1764
 
1625
- def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dictionary: dict, txt: str,
1626
- directive: str = "display") -> str | None:
1765
+ def process_per_proj_upsert_command(egeria_client: ProjectManager, txt: str, directive: str = "display") -> str | None:
1627
1766
  """
1628
1767
  Processes a personal project create or update command by extracting key attributes such as
1629
1768
  glossary name, language, description, and usage from the given cell.