pyegeria 5.3.8.1__py3-none-any.whl → 5.3.8.3__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.
@@ -11,28 +11,26 @@ import sys
11
11
  from datetime import datetime
12
12
  from typing import List, Optional
13
13
 
14
- from prompt_toolkit.filters import Always
15
14
  from rich import print
16
15
  from rich.console import Console
17
16
  from rich.markdown import Markdown
18
17
 
19
18
  from pyegeria import body_slimmer
20
- from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_TERMS_FOUND, NO_ELEMENTS_FOUND,
21
- NO_PROJECTS_FOUND, \
19
+ from pyegeria._globals import (NO_GLOSSARIES_FOUND, NO_ELEMENTS_FOUND, NO_PROJECTS_FOUND, \
22
20
  NO_CATEGORIES_FOUND)
21
+ from pyegeria.dr_egeria_state import get_element_dictionary, update_element_dictionary, find_key_with_value
23
22
  from pyegeria.egeria_tech_client import EgeriaTech
24
-
25
23
  # from pyegeria.md_processing_helpers import process_q_name_list
26
24
  from pyegeria.project_manager_omvs import ProjectManager
27
- from pyegeria.shared_state import get_element_dictionary, update_element_dictionary, find_key_with_value
28
25
 
29
26
  EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
30
27
  console = Console(width=EGERIA_WIDTH)
31
28
 
32
- command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term",
33
- "Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
34
- "Create Solution Blueprint", "Update Solution Blueprint", "Create Solution Component",
35
- "Update Solution Component", ]
29
+ command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms",
30
+ "List Glossary Terms", "Create Personal Project", "Update Personal Project", "Create Category",
31
+ "Update Category", "Create Solution Blueprint", "Update Solution Blueprint",
32
+ "Create Solution Component", "Update Solution Component", "Set Parent Category",
33
+ "UnSet Parent Category", "Unset Parent Category"]
36
34
  # verbosity - verbose, quiet, debug
37
35
  debug_level = "verbose"
38
36
  message_types = {
@@ -47,15 +45,25 @@ pre_command = "\n---\n==> Processing command:"
47
45
  command_seperator = Markdown("\n---\n")
48
46
 
49
47
  GLOSSARY_NAME_LABELS = ["Glossary Name", "Glossary", "Glossaries", "Owning Glossary", "In Glossary"]
50
- CATEGORY_NAME_LABELS = [ "Glossary Category Name", "Glossary Category", "Glossary Categories", "Category Name", "Category", "Categories"]
51
- TERM_NAME_LABELS= ["Glossary Term Name", "Glossary Term", "Glossary Terms", "Term Name", "Term", "Terms", "Term Names"]
48
+ CATEGORY_NAME_LABELS = ["Glossary Category Name", "Glossary Category", "Glossary Categories", "Category Name",
49
+ "Category", "Categories"]
50
+ PARENT_CATEGORY_LABELS = ["Parent Category Name", "Parent Category", "parent category name", "parent category"]
51
+ CHILD_CATEGORY_LABELS = ["Child Category Name", "Child Category", "child category name", "child category"]
52
+ TERM_NAME_LABELS = ["Glossary Term Name", "Glossary Term", "Glossary Terms", "Term Name", "Term", "Terms", "Term Names"]
52
53
  PROJECT_NAME_LABELS = ["Project Name", "Project", "Project Names", "Projects"]
53
- BLUEPRINT_NAME_LABELS = ["Solution Blueprint Name", "Solution Blueprint", "Solution Blueprints", "Blueprint Name", "Blueprint", "Blueprints"]
54
- COMPONENT_NAME_LABELS = ["Solution Component Name", "Solution Component", "Solution Components", "Component Name", "Component", "Components", "Parent Components", "Parent Component"]
54
+ BLUEPRINT_NAME_LABELS = ["Solution Blueprint Name", "Solution Blueprint", "Solution Blueprints", "Blueprint Name",
55
+ "Blueprint", "Blueprints"]
56
+ COMPONENT_NAME_LABELS = ["Solution Component Name", "Solution Component", "Solution Components", "Component Name",
57
+ "Component", "Components", "Parent Components", "Parent Component"]
55
58
  SOLUTION_ROLE_LABELS = ["Solution Role Name", "Solution Role", "Solution Roles", "Role Name", "Role", "Roles"]
56
- SOLUTION_ACTOR_ROLE_LABELS = [ "Solution Actor Role Name", "Solution Actor Role Names","Solution Actor Role", "Solution Actor Roles", "Actor Role Name", "Actor Role", "Actor Roles", "Actor Role Names"]
57
- SOLUTION_LINKING_ROLE_LABELS = [ "Solution Linking Role Name", "Solution Linking Role Names", "Solution Linking Role", "Solution Linking Roles", "Linking Role Name", "Linking Role", "Linking Roles", "Linking Role Names"]
58
- GUID_LABELS = ['GUID','guid']
59
+ SOLUTION_ACTOR_ROLE_LABELS = ["Solution Actor Role Name", "Solution Actor Role Names", "Solution Actor Role",
60
+ "Solution Actor Roles", "Actor Role Name", "Actor Role", "Actor Roles",
61
+ "Actor Role Names"]
62
+ SOLUTION_LINKING_ROLE_LABELS = ["Solution Linking Role Name", "Solution Linking Role Names", "Solution Linking Role",
63
+ "Solution Linking Roles", "Linking Role Name", "Linking Role", "Linking Roles",
64
+ "Linking Role Names"]
65
+ GUID_LABELS = ['GUID', 'guid']
66
+
59
67
 
60
68
  def render_markdown(markdown_text: str) -> None:
61
69
  """Renders the given markdown text in the console."""
@@ -71,6 +79,13 @@ def is_valid_iso_date(date_text) -> bool:
71
79
  return False
72
80
 
73
81
 
82
+ def set_debug_level(directive: str) -> None:
83
+ """Sets the debug level for the script."""
84
+ global debug_level
85
+ if directive == "display":
86
+ debug_level = "display-only"
87
+
88
+
74
89
  def get_current_datetime_string():
75
90
  """Returns the current date and time as a human-readable string."""
76
91
  now = datetime.now().strftime('%Y-%m-%d %H:%M')
@@ -137,7 +152,7 @@ def extract_command_plus(block: str) -> tuple[str, str, str] | None:
137
152
  if ' ' in clean_match:
138
153
  parts = clean_match.split(' ')
139
154
  object_action = parts[0].strip()
140
- # Join the rest of the parts to allow object_type to be one or two words
155
+ # Join the rest of the parts to allow object_type to be one or two words
141
156
  object_type = ' '.join(parts[1:]).strip()
142
157
  else:
143
158
  object_type = clean_match.split(' ')[1].strip()
@@ -183,7 +198,7 @@ def extract_attribute(text: str, labels: [str]) -> str | None:
183
198
  # Iterate over the list of labels
184
199
  for label in labels:
185
200
  # Construct pattern for the current label
186
- pattern = rf"## {re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
201
+ pattern = rf"## {re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
187
202
  match = re.search(pattern, text, re.DOTALL)
188
203
  if match:
189
204
  # Extract matched text and replace consecutive \n with a single \n
@@ -221,10 +236,13 @@ def print_msg(msg_level: str, msg: str, verbosity: str):
221
236
  print(record)
222
237
  case "debug":
223
238
  print(record)
239
+ case "display-only":
240
+ pass
224
241
  case _:
225
242
  print("Invalid verbosity level - exiting\n")
226
243
  sys.exit(1)
227
244
 
245
+
228
246
  def process_simple_attribute(txt: str, labels: [str], if_missing: str = INFO) -> str | None:
229
247
  """Process a simple attribute based on the provided labels and if_missing value.
230
248
  Extract the attribute value from the text and return it if it exists.
@@ -246,11 +264,15 @@ def process_simple_attribute(txt: str, labels: [str], if_missing: str = INFO) ->
246
264
  attribute = extract_attribute(txt, labels)
247
265
 
248
266
  if attribute is None:
249
- msg = f"Missing {labels[0]} attribute"
267
+ if if_missing == INFO:
268
+ msg = f"Optional attribute {labels[0]} missing"
269
+ else:
270
+ msg = f"Missing {labels[0]} attribute"
250
271
  print_msg(if_missing, msg, debug_level)
251
272
  return None
252
273
  return attribute
253
274
 
275
+
254
276
  def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid: str) -> str:
255
277
  """
256
278
  Updates a command by modifying the input text with corresponding actions, GUID, and qualified name.
@@ -281,7 +303,6 @@ def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid:
281
303
  if "GUID" not in txt:
282
304
  txt += f"\n## GUID\n{u_guid}\n"
283
305
 
284
-
285
306
  status = extract_attribute(txt, ["Status"])
286
307
  if command in ["Create Term", "Update Term"] and status is None:
287
308
  pattern = r"(## Status\s*\n)(.*?)(#)"
@@ -304,13 +325,13 @@ def process_provenance_command(file_path: str, txt: [str]) -> str:
304
325
  existing_prov = extracted_text # Return the cleaned text
305
326
  else:
306
327
  existing_prov = None
307
- print(f"txt is: {txt}, existing_prov: {existing_prov}")
328
+ # print(f"txt is: {txt}, existing_prov: {existing_prov}")
308
329
  existing_prov = existing_prov if existing_prov else " "
309
330
  return f"\n# Provenance:\n{existing_prov}\n{output}\n"
310
331
 
311
332
 
312
- def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: [str], txt: str, action: str,
313
- version: str = None) -> tuple[str, str, bool, bool]:
333
+ def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, element_labels: [str], txt: str,
334
+ action: str, version: str = None) -> tuple[str, str, bool, bool]:
314
335
  """
315
336
  Processes element identifiers by extracting display name and qualified name from the input text,
316
337
  checking if the element exists in Egeria, and validating the information.
@@ -341,10 +362,10 @@ def process_element_identifiers(egeria_client: EgeriaTech, element_type: str, el
341
362
  element_name = extract_attribute(txt, element_labels)
342
363
  qualified_name = extract_attribute(txt, ["Qualified Name"])
343
364
 
344
-
345
365
  if qualified_name:
346
366
  q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type,
347
- qualified_name) # Qualified name could be different if it is being updated
367
+ qualified_name) # Qualified name could be different if it
368
+ # is being updated
348
369
  else:
349
370
  q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type, element_name)
350
371
  if unique is False:
@@ -462,12 +483,12 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str) ->
462
483
  unique = True
463
484
  return el_qname, el_guid, unique, exists
464
485
 
465
- # Convert element_type to plural form for method name construction # if element_type.endswith('y'): #
466
- # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{
486
+ # Convert element_type to plural form for method name construction # if element_type.endswith('y'): # #
487
+ # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{ #
467
488
  # element_type}es" # else: # plural_type = f"{element_type}s" # # # Construct method name # method_name
468
489
  # = f"get_{plural_type}_by_name" # # # Check if the method exists on the client # if hasattr(egeria_client,
469
- # method_name): # # Call the method # method = getattr(egeria_client, method_name) # result =
470
- # method(element_name) # return result # else: # # Method doesn't exist # return f"Method {
490
+ # method_name): # # Call the method # method = getattr(egeria_client, method_name) # result = #
491
+ # method(element_name) # return result # else: # # Method doesn't exist # return f"Method { #
471
492
  # method_name} not found on client"
472
493
 
473
494
 
@@ -557,22 +578,22 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
557
578
  A string summarizing the outcome of the processing.
558
579
  """
559
580
  command, object_type, object_action = extract_command_plus(txt)
560
-
561
- display_name = process_simple_attribute(txt, ['Display Name', 'Blueprint Name'],ERROR)
581
+ set_debug_level(directive)
582
+ display_name = process_simple_attribute(txt, ['Display Name', 'Blueprint Name'], ERROR)
562
583
  description = process_simple_attribute(txt, ['Description'])
563
584
  version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
564
585
 
565
- print(Markdown(
566
- f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `"
567
- f"{directive}`\n"))
586
+ print(
587
+ Markdown(f"{pre_command} {object_action} `{object_type}` for Blueprint: `\'{display_name}\'` with directive: `"
588
+ f"{directive}`\n"))
568
589
  if display_name is None:
569
590
  valid = False
570
591
  q_name, known_guid, exists = None
571
592
  else:
572
593
  element_labels = BLUEPRINT_NAME_LABELS
573
594
  element_labels.append('Display Name')
574
- q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels,
575
- txt, object_action, version)
595
+ q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels, txt,
596
+ object_action, version)
576
597
 
577
598
  element_display = (f"\n* Command: {object_action} {object_type}\n\t* Blueprint: {display_name}\n\t"
578
599
  f"* Description: {description}\n\t"
@@ -610,11 +631,11 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
610
631
  print_msg("ALWAYS", msg, debug_level)
611
632
 
612
633
  # update with get blueprint by guid
613
- return 'Would return get blueprint by guid and return md' # egeria_client.get_terms_by_guid(
634
+ return 'Would return get blueprint by guid and return md' # egeria_client.get_terms_by_guid( #
614
635
  # known_guid, 'md')
615
636
 
616
637
  elif object_action == "Update" and directive == "validate":
617
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(
638
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid( #
618
639
  # known_guid, 'md')
619
640
 
620
641
  elif object_action == "Create":
@@ -633,7 +654,7 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, element_dictiona
633
654
  print_msg("ALWAYS", msg, debug_level)
634
655
 
635
656
  update_element_dictionary(q_name, {'guid': new_guid, 'display_name': display_name})
636
- return 'Would return get blueprint by guid results as md' # egeria_client.get_terms_by_guid(
657
+ return 'Would return get blueprint by guid results as md' # egeria_client.get_terms_by_guid( #
637
658
  # term_guid, 'MD')
638
659
 
639
660
  except Exception as e:
@@ -661,10 +682,11 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
661
682
  Returns: str
662
683
  A string summarizing the outcome of the processing.
663
684
  """
685
+ set_debug_level(directive)
664
686
  bp_qname_list = []
665
687
  command, object_type, object_action = extract_command_plus(txt)
666
688
 
667
- display_name = process_simple_attribute(txt,['Display Name', 'Solution Component Name'] , ERROR)
689
+ display_name = process_simple_attribute(txt, ['Display Name', 'Solution Component Name'], ERROR)
668
690
  description = process_simple_attribute(txt, ['Description'])
669
691
  version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
670
692
  solution_component_type = process_simple_attribute(txt, ['Solution Component Type'])
@@ -682,14 +704,16 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
682
704
  else:
683
705
  element_labels = COMPONENT_NAME_LABELS
684
706
  element_labels.append('Display Name')
685
- known_q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type, element_labels, txt,
686
- object_action, version)
707
+ known_q_name, known_guid, valid, exists = process_element_identifiers(egeria_client, object_type,
708
+ element_labels, txt, object_action,
709
+ version)
687
710
 
688
711
  if solution_blueprints: # Find information about blueprints that include this component
689
712
  msg = "Checking for blueprints that include this solution component"
690
713
  print_msg("DEBUG-INFO", msg, debug_level)
691
714
  solution_blueprints, bp_qname_list, bp_valid, bp_exist = process_q_name_list(egeria_client,
692
- 'Solution Blueprints', txt, BLUEPRINT_NAME_LABELS)
715
+ 'Solution Blueprints', txt,
716
+ BLUEPRINT_NAME_LABELS)
693
717
  if bp_exist and bp_valid:
694
718
  msg = f"Found valid blueprints that include this solution component:\n\t{solution_blueprints}"
695
719
  print_msg("INFO", msg, debug_level)
@@ -774,11 +798,11 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
774
798
  msg = f"\nUpdated Solution Component `{display_name}` with GUID {known_guid}"
775
799
  print_msg("ALWAYS", msg, debug_level)
776
800
  # update with get solution component by guid
777
- return 'Would return get Solution Component by guid and return md' #
801
+ return 'Would return get Solution Component by guid and return md' # #
778
802
  # egeria_client.get_terms_by_guid(known_guid, 'md')
779
803
 
780
804
  elif object_action == "Update" and directive == "validate":
781
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid(
805
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_terms_by_guid( #
782
806
  # known_guid, 'md')
783
807
 
784
808
  elif object_action == "Create":
@@ -796,7 +820,7 @@ def process_solution_component_upsert_command(egeria_client: EgeriaTech, element
796
820
  msg = f"\nCreated Solution Component `{display_name}` with GUID {known_guid}"
797
821
  print_msg("ALWAYS", msg, debug_level)
798
822
  update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
799
- return 'Would return get solution component by guid results as md' #
823
+ return 'Would return get solution component by guid results as md' # #
800
824
  # egeria_client.get_terms_by_guid(term_guid, 'MD')
801
825
 
802
826
  except Exception as e:
@@ -821,9 +845,12 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
821
845
  # object_type = command.split(' ')[1].strip()
822
846
  # object_action = command.split(' ')[0].strip()
823
847
  command, object_type, object_action = extract_command_plus(txt)
848
+ set_debug_level(directive)
824
849
 
825
850
  glossary_name = process_simple_attribute(txt, ['Glossary Name', 'Display Name'])
826
- print(Markdown(f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `{directive}` "))
851
+ print(Markdown(
852
+ f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `"
853
+ f"{directive}` "))
827
854
  language = process_simple_attribute(txt, ['Language'])
828
855
  description = process_simple_attribute(txt, ['Description'])
829
856
  usage = process_simple_attribute(txt, ['Usage'])
@@ -833,14 +860,14 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
833
860
  valid = False
834
861
  known_q_name, known_guid, glossary_exists = None
835
862
  else:
836
- element_labels =GLOSSARY_NAME_LABELS
863
+ element_labels = GLOSSARY_NAME_LABELS
837
864
  element_labels.append('Display Name')
838
- known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, object_type, element_labels,
839
- txt, object_action, None)
865
+ known_q_name, known_guid, valid, glossary_exists = process_element_identifiers(egeria_client, object_type,
866
+ element_labels, txt,
867
+ object_action, None)
840
868
  glossary_display = (f"\n* Command: `{command}`\n\t* Glossary Name: {glossary_name}\n\t"
841
869
  f"* Language: {language}\n\t* Description:\n{description}\n"
842
- f"* Usage: {usage}\n"
843
- )
870
+ f"* Usage: {usage}\n")
844
871
 
845
872
  if object_action == 'Update':
846
873
  guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
@@ -863,7 +890,6 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
863
890
  msg = f"It is valid to create Glossary `{glossary_name}` with:\n"
864
891
  print_msg("ALWAYS", msg, debug_level)
865
892
 
866
-
867
893
  if directive == "display":
868
894
  print(Markdown(glossary_display))
869
895
  return None
@@ -890,7 +916,8 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, element_dictionar
890
916
  if object_action == "Update":
891
917
  if not glossary_exists:
892
918
  print(
893
- f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create command\n")
919
+ f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
920
+ f"command\n")
894
921
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
895
922
 
896
923
  body = {
@@ -938,7 +965,7 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
938
965
  :return: A string summarizing the outcome of the processing.
939
966
  """
940
967
  valid = True
941
-
968
+ set_debug_level(directive)
942
969
  # command = extract_command(txt)
943
970
  # object_type = command.split(' ')[1].strip()
944
971
  # object_action = command.split(' ')[0].strip()
@@ -960,25 +987,22 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
960
987
  else:
961
988
  element_labels = CATEGORY_NAME_LABELS
962
989
  element_labels.append('Display Name')
963
- known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type, element_labels,
964
- txt, object_action, None)
965
-
990
+ known_q_name, known_guid, valid, category_exists = process_element_identifiers(egeria_client, object_type,
991
+ element_labels, txt,
992
+ object_action, None)
966
993
 
967
994
  # Check if owning glossary exists (and get qname)
968
995
  if owning_glossary_name is None:
969
996
  valid = False
970
997
  known_glossary_q_name, known_glossary__guid, glossary_exists = None
971
998
  else:
972
- known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(egeria_client,
973
- "Glossary",
974
- GLOSSARY_NAME_LABELS, txt,
975
- "Exists Required", None)
999
+ known_glossary_q_name, known_glossary_guid, valid, owning_glossary_exists = process_element_identifiers(
1000
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, "Exists Required", None)
976
1001
 
977
1002
  category_display = (
978
1003
  f"\n* Command: {command}\n\t* Category: {category_name}\n\t* In Glossary: {owning_glossary_name}\n\t"
979
1004
  f"* Description:\n{description}\n\t* Qualified Name: {q_name}\n\t")
980
1005
 
981
-
982
1006
  if object_action == 'Update':
983
1007
  guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
984
1008
  # update_description = process_simple_attribute(txt, 'Update Description')
@@ -1041,7 +1065,8 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1041
1065
  is_root = True
1042
1066
 
1043
1067
  if category_exists:
1044
- msg = f"Cannot create`{category_name}` because it already exists; result document written for category update\n"
1068
+ msg = (f"Cannot create`{category_name}` because it already exists; result document written for "
1069
+ f"category update\n")
1045
1070
  print_msg(WARNING, msg, debug_level)
1046
1071
  return update_a_command(txt, command, object_type, known_q_name, known_guid)
1047
1072
  else:
@@ -1058,7 +1083,175 @@ def process_categories_upsert_command(egeria_client: EgeriaTech, element_diction
1058
1083
  'guid': category_guid, 'display_name': category_name
1059
1084
  })
1060
1085
  print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
1061
- return egeria_client.get_categories_by_guid(category_guid, output_format='MD')
1086
+ return egeria_client.get_categories_by_guid(category_guid, output_format='DR')
1087
+
1088
+
1089
+ def process_set_categories_parent_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1090
+ directive: str = "display") -> Optional[str]:
1091
+ """
1092
+ Processes a set_parent_category command by extracting key attributes such as
1093
+ parent and child category names from the given text.
1094
+
1095
+ :param txt: A string representing the input cell to be processed for
1096
+ extracting category-related attributes.
1097
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1098
+ :return: A string summarizing the outcome of the processing.
1099
+ """
1100
+ valid = True
1101
+ set_debug_level(directive)
1102
+
1103
+ command, object_type, object_action = extract_command_plus(txt)
1104
+
1105
+ parent_category_name = process_simple_attribute(txt, PARENT_CATEGORY_LABELS, "ERROR")
1106
+ child_category_name = process_simple_attribute(txt, CHILD_CATEGORY_LABELS, "ERROR")
1107
+ print(Markdown(f"{pre_command} `{command}` for parent category: `\'{parent_category_name}\'` \n\t"
1108
+ f"and child category: `\'{child_category_name}\'` \nwith directive: `{directive}` "))
1109
+
1110
+ if parent_category_name is None or child_category_name is None:
1111
+ valid = False
1112
+ else:
1113
+ parent_cat_q_name, parent_cat_guid, parent_cat_valid, parent_cat_exists = (
1114
+ get_element_by_name(egeria_client, 'Glossary Categories', parent_category_name))
1115
+ child_cat_q_name, child_cat_guid, child_cat_valid, child_cat_exists = (
1116
+ get_element_by_name(egeria_client, 'Glossary Categories', child_category_name))
1117
+
1118
+ # Check if category exists (and get qname and guid)
1119
+
1120
+ if parent_cat_exists and child_cat_exists:
1121
+ valid = True
1122
+ msg = f" Both categories {parent_category_name} and {child_category_name} exist\n"
1123
+ print_msg(INFO, msg, debug_level)
1124
+ if parent_cat_guid and child_cat_guid:
1125
+ msg = f" Both categories {parent_category_name} and {child_category_name} have GUIDs\n"
1126
+ print_msg(INFO, msg, debug_level)
1127
+ else:
1128
+ msg = f" Both categories {parent_category_name} and {child_category_name} do not have GUIDs\n"
1129
+ print_msg(ERROR, msg, debug_level)
1130
+ valid = False
1131
+
1132
+
1133
+ else:
1134
+ valid = False
1135
+ msg = f"Both categories {parent_category_name} and {child_category_name} do NOT exist\n"
1136
+ print_msg(ERROR, msg, debug_level)
1137
+
1138
+ category_display = (f"\n* Command: {command}\n\t* Parent Category: {parent_category_name}\n\t\t"
1139
+ f"* Qualified Name: {parent_cat_q_name}\n\t\t* GUID: {parent_cat_guid}\n\t"
1140
+ f"* Child Category:\n{child_category_name}\n\t\t* Qualified Name: {child_cat_q_name}\n\t\t"
1141
+ f"* GUID: {child_cat_guid}\n")
1142
+
1143
+ # if object_action == 'Remove Parent Category':
1144
+ # parent_guid = process_simple_attribute(txt, ['GUID', 'guid', 'Guid'])
1145
+ #
1146
+ # category_display += (f"* GUID: {guid}\n\n")
1147
+ # if not category_exists:
1148
+ # msg = f"Category {category_name} can't be updated; {category_name} not found."
1149
+ # print_msg(ERROR, msg, debug_level)
1150
+ # valid = False
1151
+ # else:
1152
+ # msg = f"Glossary can be updated; {category_name} found"
1153
+ # print_msg(ALWAYS, msg, debug_level)
1154
+ #
1155
+ # elif object_action == "Create":
1156
+ # if category_exists:
1157
+ # msg = f"Category {category_name} can't be created because it already exists.\n"
1158
+ # print_msg("ERROR", msg, debug_level)
1159
+ # valid = False
1160
+ # elif valid:
1161
+ # msg = f"It is valid to create Category `{category_name}` with:\n"
1162
+ # print_msg("ALWAYS", msg, debug_level)
1163
+
1164
+ if directive == "display":
1165
+ print(Markdown(category_display))
1166
+ return None
1167
+
1168
+ elif directive == "validate":
1169
+ if valid:
1170
+ print(Markdown(category_display))
1171
+ else:
1172
+ msg = f"Validation failed for {object_type} `{parent_category_name}`\n"
1173
+ print_msg(ERROR, msg, debug_level)
1174
+ print(Markdown(category_display))
1175
+ return valid
1176
+
1177
+ elif directive == "process":
1178
+ if valid:
1179
+ print(Markdown(category_display))
1180
+ else:
1181
+ msg = f"* --> Validation failed for {object_type} `{parent_category_name}`\n"
1182
+ print_msg(ERROR, msg, debug_level)
1183
+ print(Markdown(category_display))
1184
+ return None
1185
+
1186
+ if object_action in ["Set", "Set Parent"]:
1187
+ egeria_client.set_parent_category(parent_cat_guid, child_cat_guid)
1188
+ print_msg(ALWAYS, f"Set parent category of `{child_category_name}` to `{parent_category_name}`",
1189
+ debug_level)
1190
+ output_txt = txt.replace("Set Parent", "UnSet Parent")
1191
+ return output_txt
1192
+
1193
+ elif object_action in ["UnSet", "UnSet Parent", "Unset Parent", "Unset", "Remove Parent"]:
1194
+ egeria_client.remove_parent_category(parent_cat_guid, child_cat_guid)
1195
+ print_msg(ALWAYS, f"UnSet parent category `{child_category_name}` from {parent_category_name}", debug_level)
1196
+ output_txt = txt.replace("UnSet Parent", "Set Parent")
1197
+ return output_txt
1198
+
1199
+ def process_term_list_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
1200
+ directive: str = "display") -> Optional[str]:
1201
+ """ List terms as a markdown table. Filter based on optional search string. """
1202
+ set_debug_level(directive)
1203
+ valid = True
1204
+ command = extract_command(txt)
1205
+ object_type = command.split(' ')[1].strip()
1206
+ object_action = command.split(' ')[0].strip()
1207
+ known_glossary_q = ""
1208
+ known_glossary_guid = ""
1209
+ glossary_exists = False
1210
+ glossary_valid = False
1211
+
1212
+
1213
+ search_string = process_simple_attribute(txt, ['Search String', 'Filter'])
1214
+ if search_string is None:
1215
+ search_string = ''
1216
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1217
+
1218
+ glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1219
+ if glossary is not None:
1220
+ _, glossary_guid, _, glossary_exists = get_element_by_name(
1221
+ egeria_client, "Glossary", glossary)
1222
+ msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
1223
+ print_msg(INFO, msg, debug_level)
1224
+ else:
1225
+ glossary_guid= None
1226
+ msg = f"No glossary found"
1227
+ print_msg(INFO, msg, debug_level)
1228
+
1229
+
1230
+ request_display = f"\n* Search String: {search_string}\n* Glossary: {glossary}\n"
1231
+
1232
+ if directive == "display":
1233
+ print(Markdown(request_display))
1234
+ return None
1235
+ elif directive == "validate":
1236
+ print(Markdown(request_display))
1237
+ return valid
1238
+ elif directive == "process":
1239
+ try:
1240
+ print(Markdown(request_display))
1241
+ if not valid: # First validate the term before we process it
1242
+ return None
1243
+
1244
+ md_table = egeria_client.find_glossary_terms(search_string,glossary_guid, output_format = "LIST")
1245
+
1246
+ return md_table
1247
+
1248
+ except Exception as e:
1249
+ print(f"{ERROR}Error creating Glossary Term list: {e}")
1250
+ console.print_exception(show_locals=True)
1251
+ return None
1252
+
1253
+
1254
+
1062
1255
 
1063
1256
 
1064
1257
  def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: dict, txt: str,
@@ -1075,7 +1268,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1075
1268
  valid = True
1076
1269
  categories_list = None
1077
1270
  cats_exist = True
1078
-
1271
+ set_debug_level(directive)
1079
1272
  known_q_name = None
1080
1273
  command = extract_command(txt)
1081
1274
  object_type = command.split(' ')[1].strip()
@@ -1100,9 +1293,9 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1100
1293
  else:
1101
1294
  element_labels = TERM_NAME_LABELS
1102
1295
  element_labels.append('Display Name')
1103
- known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type, element_labels,
1104
- txt, object_action, version)
1105
-
1296
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1297
+ element_labels, txt, object_action,
1298
+ version)
1106
1299
 
1107
1300
  # get the glossary qualified name this term is in
1108
1301
  glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
@@ -1122,7 +1315,8 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1122
1315
  msg = "Checking for categories that classify this term"
1123
1316
  print_msg("DEBUG-INFO", msg, debug_level)
1124
1317
  categories_list, cat_q_name_list, cat_valid, cat_exist = process_q_name_list(egeria_client,
1125
- 'Glossary Categories', txt, CATEGORY_NAME_LABELS)
1318
+ 'Glossary Categories', txt,
1319
+ CATEGORY_NAME_LABELS)
1126
1320
  if cat_exist and cat_valid:
1127
1321
  msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
1128
1322
  print_msg("INFO", msg, debug_level)
@@ -1133,8 +1327,6 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1133
1327
  cat_exist = cat_valid = False
1134
1328
  cat_q_name_list = None
1135
1329
 
1136
-
1137
-
1138
1330
  if object_action == "Update": # check to see if provided information exists and is consistent with existing info
1139
1331
  term_guid = process_simple_attribute(txt, GUID_LABELS)
1140
1332
  update_description = process_simple_attribute(txt, ['Update Description'])
@@ -1146,7 +1338,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1146
1338
  f"\n\t* Update Description: {update_description}\n")
1147
1339
  if not term_exists:
1148
1340
  msg = f"Update request invalid, Term {term_name} does not exist\n"
1149
- print_msg(ERROR,msg, debug_level)
1341
+ print_msg(ERROR, msg, debug_level)
1150
1342
  valid = False
1151
1343
 
1152
1344
  elif object_action == 'Create': # if the command is create, check that it doesn't already exist
@@ -1160,8 +1352,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1160
1352
  print_msg(ERROR, msg, debug_level)
1161
1353
  else:
1162
1354
  msg = f"It is valid to create Term `{term_name}`"
1163
- print_msg(ALWAYS,msg, debug_level)
1164
-
1355
+ print_msg(ALWAYS, msg, debug_level)
1165
1356
 
1166
1357
  if directive == "display":
1167
1358
  print(Markdown(term_display))
@@ -1187,11 +1378,13 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1187
1378
  egeria_client.update_term(known_guid, body_slimmer(body))
1188
1379
  if cat_exist and cat_valid:
1189
1380
  add_term_to_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
1190
- print_msg(ALWAYS, f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`", debug_level)
1381
+ print_msg(ALWAYS,
1382
+ f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
1383
+ debug_level)
1191
1384
  return egeria_client.get_terms_by_guid(known_guid,
1192
1385
  'md') # return update_a_command(txt, command, object_type,
1193
1386
  # known_q_name, known_guid)
1194
- elif object_action == "Update" and directive == "validate": # is sthis reachable?
1387
+ elif object_action == "Update" and directive == "validate": # is sthis reachable?
1195
1388
  return egeria_client.get_terms_by_guid(known_guid, 'md')
1196
1389
 
1197
1390
  elif object_action == "Create":
@@ -1207,7 +1400,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, element_dictionary: d
1207
1400
  glossary_guid = cached.get('guid', None)
1208
1401
  if glossary_guid is None:
1209
1402
  msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
1210
- print_msg(WARNING, msg, debug_level) # should this ever occur?
1403
+ print_msg(WARNING, msg, debug_level) # should this ever occur?
1211
1404
  return None
1212
1405
  else:
1213
1406
  glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
@@ -1259,6 +1452,7 @@ def process_per_proj_upsert_command(egeria_client: ProjectManager, element_dicti
1259
1452
  object = command.split()
1260
1453
  object_type = f"{object[1]} {object[2]}"
1261
1454
  object_action = object[0]
1455
+ set_debug_level(directive)
1262
1456
 
1263
1457
  project_name = process_simple_attribute(txt, ['Project Name'])
1264
1458
  description = process_simple_attribute(txt, ['Description'])