pyegeria 5.3.8.9__py3-none-any.whl → 5.3.8.10__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.
@@ -30,7 +30,7 @@ command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term
30
30
  "List Glossary Structure", "List Glossaries", "List Categories", "List Glossary Categories",
31
31
  "Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
32
32
  "Create Solution Blueprint", "Update Solution Blueprint", "Create Solution Component",
33
- "Update Solution Component", ]
33
+ "Update Solution Component", "Create Term-Term Relationship", "Update Term-Term Relationship",]
34
34
  # verbosity - verbose, quiet, debug
35
35
  debug_level = "debug"
36
36
  message_types = {
@@ -69,7 +69,19 @@ SEARCH_LABELS = ['Search String', 'Filter']
69
69
  GUID_LABELS = ['GUID', 'guid']
70
70
 
71
71
  ELEMENT_OUTPUT_FORMATS = ["LIST", "DICT", "MD", "FORM", "REPORT"]
72
-
72
+ TERM_RELATIONSHPS = [
73
+ "Synonym",
74
+ "Translation",
75
+ "PreferredTerm",
76
+ "TermISATYPEOFRelationship",
77
+ "TermTYPEDBYRelationship",
78
+ "Antonym",
79
+ "ReplacementTerm",
80
+ "ValidValue",
81
+ "TermHASARelationship",
82
+ "RelatedTerm",
83
+ "ISARelationship"
84
+ ]
73
85
 
74
86
  def render_markdown(markdown_text: str) -> None:
75
87
  """Renders the given markdown text in the console."""
@@ -535,8 +547,8 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str) ->
535
547
  unique = True
536
548
  return el_qname, el_guid, unique, exists
537
549
 
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"{ # #
550
+ # Convert element_type to plural form for method name construction # if element_type.endswith('y'): # # # #
551
+ # plural_type = f"{element_type[:-1]}ies" # elif element_type.endswith('s'): # plural_type = f"{ # # #
540
552
  # element_type}es" # else: # plural_type = f"{element_type}s" # # # Construct method name # method_name
541
553
  # = f"get_{plural_type}_by_name" # # # Check if the method exists on the client # if hasattr(egeria_client,
542
554
  # method_name): # # Call the method # method = getattr(egeria_client, method_name) # result = #
@@ -682,11 +694,11 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, direct
682
694
  print_msg("ALWAYS", msg, debug_level)
683
695
 
684
696
  # update with get blueprint by guid
685
- return 'Would return get blueprint by guid and return md' # egeria_client.get_term_by_guid( # #
697
+ return 'Would return get blueprint by guid and return md' # egeria_client.get_term_by_guid( # # #
686
698
  # known_guid, 'md')
687
699
 
688
700
  elif object_action == "Update" and directive == "validate":
689
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # #
701
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # # #
690
702
  # known_guid, 'md')
691
703
 
692
704
  elif object_action == "Create":
@@ -707,12 +719,16 @@ def process_blueprint_upsert_command(egeria_client: EgeriaTech, txt: str, direct
707
719
  update_element_dictionary(q_name, {'guid': new_guid, 'display_name': display_name})
708
720
  return 'Would return get blueprint by guid results as md' # egeria_client.get_term_by_guid( #
709
721
  # term_guid, 'MD')
722
+ else:
723
+ return None
710
724
 
711
725
  except Exception as e:
712
726
  msg = f"{ERROR}Error creating term {display_name}: {e}"
713
727
  print_msg("ERROR", msg, debug_level)
714
728
  console.print_exception(show_locals=True)
715
729
  return None
730
+ else:
731
+ return None
716
732
 
717
733
 
718
734
  def process_solution_component_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> \
@@ -775,7 +791,10 @@ Optional[str]:
775
791
  print_msg("INFO", msg, debug_level)
776
792
  else:
777
793
  parent_components, parent_qname_list, parents_valid, parent_components_exist = process_name_list(egeria_client,
778
- 'Parent Components', txt, COMPONENT_NAME_LABELS)
794
+ 'Parent '
795
+ 'Components',
796
+ txt,
797
+ COMPONENT_NAME_LABELS)
779
798
  if parent_components_exist and parents_valid:
780
799
  msg = f"Found valid parent components that include this solution component:\n\t{parent_qname_list}"
781
800
  print_msg("INFO", msg, debug_level)
@@ -848,11 +867,11 @@ Optional[str]:
848
867
  msg = f"\nUpdated Solution Component `{display_name}` with GUID {known_guid}"
849
868
  print_msg("ALWAYS", msg, debug_level)
850
869
  # update with get solution component by guid
851
- return 'Would return get Solution Component by guid and return md' # # #
870
+ return 'Would return get Solution Component by guid and return md' # # # #
852
871
  # egeria_client.get_term_by_guid(known_guid, 'md')
853
872
 
854
873
  elif object_action == "Update" and directive == "validate":
855
- return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # #
874
+ return 'Would call get_blueprint_by_guid and return md' # egeria_client.get_term_by_guid( # # #
856
875
  # known_guid, 'md')
857
876
 
858
877
  elif object_action == "Create":
@@ -870,7 +889,7 @@ Optional[str]:
870
889
  msg = f"\nCreated Solution Component `{display_name}` with GUID {known_guid}"
871
890
  print_msg("ALWAYS", msg, debug_level)
872
891
  update_element_dictionary(known_q_name, {'guid': known_guid, 'display_name': display_name})
873
- return 'Would return get solution component by guid results as md' # # #
892
+ return 'Would return get solution component by guid results as md' # # # #
874
893
  # egeria_client.get_term_by_guid(term_guid, 'MD')
875
894
 
876
895
  except Exception as e:
@@ -878,7 +897,8 @@ Optional[str]:
878
897
  print_msg("ERROR", msg, debug_level)
879
898
  console.print_exception(show_locals=True)
880
899
  return None
881
-
900
+ else:
901
+ return None
882
902
 
883
903
  def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
884
904
  """
@@ -894,14 +914,15 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directi
894
914
  command, object_type, object_action = extract_command_plus(txt)
895
915
  set_debug_level(directive)
896
916
 
897
- glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS)
917
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
898
918
  print(Markdown(
899
919
  f"{pre_command} `{object_action}` `{object_type}` for glossary: `\'{glossary_name}\'` with directive: `"
900
920
  f"{directive}` "))
901
- language = process_simple_attribute(txt, ['Language'])
902
- description = process_simple_attribute(txt, ['Description'])
903
- usage = process_simple_attribute(txt, ['Usage'])
904
- q_name = process_simple_attribute(txt, ['Qualified Name'])
921
+ language = process_simple_attribute(txt, ['Language'], INFO)
922
+ description = process_simple_attribute(txt, ['Description'], INFO)
923
+ usage = process_simple_attribute(txt, ['Usage'], INFO)
924
+ q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
925
+ valid = True
905
926
 
906
927
  if glossary_name is None:
907
928
  valid = False
@@ -1053,7 +1074,7 @@ def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directi
1053
1074
 
1054
1075
  if parent_category_name:
1055
1076
  _, parent_guid, parent_valid, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1056
- parent_category_name)
1077
+ parent_category_name)
1057
1078
  else:
1058
1079
  parent_guid = None
1059
1080
  parent_exists = False
@@ -1198,7 +1219,7 @@ def update_category_parent(egeria_client, category_guid: str, parent_category_na
1198
1219
  if isinstance(current_parent, str) and "No Parent Category found" in current_parent:
1199
1220
  # No parent currently set, need to set it
1200
1221
  _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1201
- parent_category_name)
1222
+ parent_category_name)
1202
1223
 
1203
1224
  if parent_exists and parent_guid:
1204
1225
  egeria_client.set_parent_category(parent_guid, category_guid)
@@ -1219,7 +1240,7 @@ def update_category_parent(egeria_client, category_guid: str, parent_category_na
1219
1240
 
1220
1241
  # Then set the new parent
1221
1242
  _, parent_guid, _, parent_exists = get_element_by_name(egeria_client, 'Glossary Categories',
1222
- parent_category_name)
1243
+ parent_category_name)
1223
1244
 
1224
1245
  if parent_exists and parent_guid:
1225
1246
  egeria_client.set_parent_category(parent_guid, category_guid)
@@ -1245,170 +1266,465 @@ def update_category_parent(egeria_client, category_guid: str, parent_category_na
1245
1266
  return outcome
1246
1267
 
1247
1268
 
1248
- def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1249
- """ List terms as a markdown table. Filter based on optional search string. """
1250
- set_debug_level(directive)
1269
+ def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1270
+ """
1271
+ Processes a term create or update command by extracting key attributes such as
1272
+ term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
1273
+
1274
+ :param txt: A string representing the input cell to be processed for
1275
+ extracting glossary-related attributes.
1276
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1277
+ :return: A string summarizing the outcome of the processing.
1278
+ """
1251
1279
  valid = True
1280
+ categories_list = None
1281
+ cats_exist = False
1282
+ set_debug_level(directive)
1283
+ known_q_name = None
1252
1284
  command = extract_command(txt)
1285
+ object_type = command.split(' ')[1].strip()
1286
+ object_action = command.split(' ')[0].strip()
1253
1287
 
1254
- search_string = process_simple_attribute(txt, SEARCH_LABELS)
1255
- if search_string is None:
1256
- search_string = '*'
1257
- print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1288
+ term_name = process_simple_attribute(txt, ['Term Name', 'Display Name'], ERROR)
1289
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1290
+ summary = process_simple_attribute(txt, ['Summary'],INFO)
1291
+ description = process_simple_attribute(txt, ['Description'], INFO)
1292
+ abbreviation = process_simple_attribute(txt, ['Abbreviation'], INFO)
1293
+ examples = process_simple_attribute(txt, ['Examples'], INFO)
1294
+ usage = process_simple_attribute(txt, ['Usage'], INFO)
1295
+ status = process_simple_attribute(txt, ['Status'])
1296
+ status = status.upper() if status else 'DRAFT'
1297
+ version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"], INFO)
1298
+ q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
1258
1299
 
1259
- glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1260
- if glossary is not None:
1261
- _, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
1262
- msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
1263
- print_msg(INFO, msg, debug_level)
1300
+ aliases = process_simple_attribute(txt, ['Aliases'], INFO)
1301
+ if aliases:
1302
+ alias_list = list(filter(None, re.split(r'[,\s]+', aliases.strip())))
1264
1303
  else:
1265
- glossary_guid = None
1266
- msg = f"No glossary found"
1267
- print_msg(INFO, msg, debug_level)
1304
+ alias_list = None
1268
1305
 
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:
1306
+
1307
+
1308
+ # validate term name and get existing qualified_name and guid if they exist
1309
+ if term_name is None:
1273
1310
  valid = False
1274
- print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1311
+ known_q_name, known_guid, term_exists = None
1312
+ else:
1313
+ element_labels = TERM_NAME_LABELS
1314
+ element_labels.append('Display Name')
1315
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1316
+ element_labels, txt, object_action,
1317
+ version)
1275
1318
 
1276
- request_display = (f"\n\t* Search String: {search_string}\n\t* Glossary: {glossary}\n\t* Output Format: "
1277
- f"{output_format}\n")
1319
+ # get the glossary qualified name this term is in
1320
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
1321
+ if glossary_name is None:
1322
+ valid = False
1323
+ known_glossary_guid = None
1324
+ known_glossary_q_name = None
1325
+ glossary_valid = False
1326
+ glossary_exists = False
1327
+ else:
1328
+ known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
1329
+ egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
1330
+
1331
+ # process categories, if present
1332
+ categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
1333
+ if categories: # Find information about categoriess that classify this term
1334
+ msg = "Checking for categories that classify this term"
1335
+ print_msg("DEBUG-INFO", msg, debug_level)
1336
+ categories_list, cat_q_name_list, cats_valid, cats_exist = process_name_list(egeria_client, 'Glossary Categories',
1337
+ txt, CATEGORY_NAME_LABELS)
1338
+ if cats_exist and cats_valid:
1339
+ msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
1340
+ print_msg("INFO", msg, debug_level)
1341
+ else:
1342
+ msg = "No valid glossary categories found."
1343
+ print_msg("INFO", msg, debug_level)
1344
+ else:
1345
+ cats_exist = cats_valid = False
1346
+ cat_q_name_list = None
1347
+
1348
+ if object_action == "Update": # check to see if provided information exists and is consistent with existing info
1349
+ term_guid = process_simple_attribute(txt, GUID_LABELS)
1350
+ update_description = process_simple_attribute(txt, ['Update Description'])
1351
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1352
+ f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t"
1353
+ f"* Categories: {categories}\n\t"
1354
+ f"* Summary: {summary}\n\t* Description: {description}\n\t"
1355
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1356
+ f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}"
1357
+ f"\n\t* Update Description: {update_description}\n")
1358
+ if not term_exists:
1359
+ msg = f"Update request invalid, Term {term_name} does not exist\n"
1360
+ print_msg(ERROR, msg, debug_level)
1361
+ valid = False
1362
+
1363
+ elif object_action == 'Create': # if the command is create, check that it doesn't already exist
1364
+ term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1365
+ f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
1366
+ f"* Qualified Name: {q_name}\n\t* Aliases: {aliases}\n\t* Description: {description}\n\t"
1367
+ f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1368
+ f"* Version: {version}\n\t* Status: {status}\n")
1369
+ if term_exists:
1370
+ msg = f"Term `{term_name}` cannot be created since it already exists\n"
1371
+ print_msg(ERROR, msg, debug_level)
1372
+ else:
1373
+ msg = f"It is valid to create Term `{term_name}`"
1374
+ print_msg(ALWAYS, msg, debug_level)
1278
1375
 
1279
1376
  if directive == "display":
1280
- print(Markdown(request_display))
1377
+ print(Markdown(term_display))
1281
1378
  return None
1282
1379
  elif directive == "validate":
1283
- print(Markdown(request_display))
1380
+ print(Markdown(term_display))
1284
1381
  return valid
1285
1382
  elif directive == "process":
1286
1383
  try:
1287
- print(Markdown(request_display))
1288
1384
  if not valid: # First validate the term before we process it
1289
1385
  return None
1386
+ print(Markdown(term_display))
1387
+ if object_action == "Update" and directive == "process":
1388
+ if not term_exists:
1389
+ return None
1390
+ body = {
1391
+ "class": "ReferenceableRequestBody", "elementProperties": { "displayName": term_name,
1392
+ "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "aliases": alias_list, "summary": summary,
1393
+ "description": description, "abbreviation": abbreviation, "examples": examples, "usage": usage,
1394
+ "publishVersionIdentifier": version, "status": status
1395
+ }, "updateDescription": update_description
1396
+ }
1397
+ egeria_client.update_term(known_guid, body_slimmer(body), is_merge_update=False)
1398
+ # if cat_exist and cat_valid:
1399
+ update_term_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
1400
+ print_msg(ALWAYS,
1401
+ f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
1402
+ debug_level)
1403
+ return egeria_client.get_term_by_guid(known_guid,
1404
+ 'md') # return update_a_command(txt, command, object_type,
1405
+ # known_q_name, known_guid)
1406
+ elif object_action == "Update" and directive == "validate": # is sthis reachable?
1407
+ return egeria_client.get_term_by_guid(known_guid, 'md')
1290
1408
 
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)
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)
1305
- return md_table
1409
+ elif object_action == "Create":
1410
+ if term_exists:
1411
+ msg = f"Term {term_name} exists so result document modifies term create to term update"
1412
+ print_msg(INFO, msg, debug_level)
1413
+ return update_a_command(txt, command, object_type, q_name, known_guid)
1414
+ else:
1415
+ ## get the guid for the glossary from the name - first look in cache
1416
+ cached = get_element_dictionary().get(known_glossary_q_name, None)
1306
1417
 
1418
+ if cached is not None:
1419
+ glossary_guid = cached.get('guid', None)
1420
+ if glossary_guid is None:
1421
+ msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
1422
+ print_msg(WARNING, msg, debug_level) # should this ever occur?
1423
+ return None
1424
+ else:
1425
+ glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
1426
+ if glossary_guid == NO_ELEMENTS_FOUND:
1427
+ msg = f"Glossary {known_glossary_q_name} not found"
1428
+ print_msg(WARNING, msg, debug_level)
1429
+ return None
1430
+ term_body = {
1431
+ "class": "ReferenceableRequestBody", "elementProperties": {
1432
+ "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "displayName": term_name,
1433
+ "aliases": alias_list, "summary": summary, "description": description, "abbreviation": abbreviation,
1434
+ "examples": examples, "usage": usage, "publishVersionIdentifier": version
1435
+ # "additionalProperties":
1436
+ # {
1437
+ # "propertyName1": "xxxx",
1438
+ # "propertyName2": "xxxx"
1439
+ # }
1440
+ }, "initialStatus": status
1441
+ }
1442
+ term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, body_slimmer(term_body))
1443
+ if term_guid == NO_ELEMENTS_FOUND:
1444
+ print(f"{ERROR}Term {term_name} not created")
1445
+ return None
1446
+ if cats_exist and categories is not None:
1447
+ update_term_categories(egeria_client, term_guid, cats_exist, cat_q_name_list)
1448
+ update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
1449
+ print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
1450
+ return egeria_client.get_term_by_guid(term_guid,
1451
+ 'MD') # return update_a_command(txt, command,
1452
+ # object_type, q_name, term_guid)
1307
1453
  except Exception as e:
1308
- print(f"{ERROR}Error performing {command}: {e}")
1454
+ print(f"{ERROR}Error creating term {term_name}: {e}")
1309
1455
  console.print_exception(show_locals=True)
1310
1456
  return None
1311
1457
  else:
1312
1458
  return None
1313
1459
 
1314
1460
 
1315
- def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1316
- """ List terms as a markdown table. Filter based on optional search string. """
1461
+
1462
+
1463
+ def process_create_term_term_relationship_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1464
+ """ Relate two terms through the specified relationship. ."""
1317
1465
  set_debug_level(directive)
1318
1466
  valid = True
1319
1467
  command = extract_command(txt)
1468
+ object_type = command.split(' ')[1].strip()
1469
+ object_action = command.split(' ')[0].strip()
1470
+ term1_guid = None
1471
+ term2_guid = None
1320
1472
 
1321
- search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
1322
- if search_string is None:
1323
- search_string = '*'
1324
- print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1325
1473
 
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:
1474
+ term_relationship = process_simple_attribute(txt, ["Term Relationship"], "ERROR")
1475
+ if term_relationship not in TERM_RELATIONSHPS:
1330
1476
  valid = False
1331
- print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1332
1477
 
1333
- request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
1478
+ print(Markdown(f"{pre_command} `{command}` for term relationship: `{term_relationship}` with directive: `{directive}` "))
1479
+
1480
+ term1_q_name, term1_guid, term1_valid, term1_exists = process_element_identifiers(egeria_client, object_type, ["Term 1 Name"], txt,
1481
+ "Exists Required", None )
1482
+
1483
+ term2_q_name, term2_guid, term2_valid, term2_exists = process_element_identifiers(egeria_client, object_type, ["Term 2 Name"], txt,
1484
+ "Exists Required", None )
1485
+
1486
+ request_display = (f"\n\t* Term 1 Qualified Name: {term1_q_name}\n\t* Term 2 Qualified Name {term2_q_name}\n\t"
1487
+ f"* Term Relationship: {term_relationship}")
1488
+
1489
+ if not(term1_valid and term2_valid and term1_exists and term2_exists):
1490
+ valid = False
1334
1491
 
1335
1492
  if directive == "display":
1336
- print(Markdown(request_display))
1493
+ print(request_display)
1337
1494
  return None
1338
1495
  elif directive == "validate":
1339
- print(Markdown(request_display))
1340
- return valid
1496
+ print(request_display)
1497
+ return str(valid)
1341
1498
  elif directive == "process":
1342
1499
  try:
1343
- print(Markdown(request_display))
1500
+ print(request_display)
1344
1501
  if not valid: # First validate the term before we process it
1345
1502
  return None
1503
+ egeria_client.add_relationship_between_terms(term1_guid, term2_guid, term_relationship)
1504
+ print_msg(ALWAYS, f"Relationship `{term_relationship}` created", debug_level)
1505
+ update_md = (f"\n\n# Update Term-Term Relationship\n\n## Term 1 Name:\n\n{term1_q_name}"
1506
+ f"\n\n## Term 2 Name\n\n{term2_q_name}\n\n## Term Relationship:\n\n{term_relationship}")
1507
+ return update_md
1346
1508
 
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
1356
1509
 
1357
1510
  except Exception as e:
1358
1511
  print(f"{ERROR}Error performing {command}: {e}")
1359
1512
  console.print_exception(show_locals=True)
1360
1513
  return None
1361
1514
  else:
1362
-
1363
1515
  return None
1364
1516
 
1365
1517
 
1366
- def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[
1367
- str]:
1368
- """ List terms as a markdown table. Filter based on optional search string. """
1369
- set_debug_level(directive)
1370
- valid = True
1371
- command = extract_command(txt)
1372
-
1373
- known_glossary_guid = ""
1374
1518
 
1375
- glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, "ERROR")
1519
+ def process_per_proj_upsert_command(egeria_client: ProjectManager, txt: str, directive: str = "display") -> str | None:
1520
+ """
1521
+ Processes a personal project create or update command by extracting key attributes such as
1522
+ glossary name, language, description, and usage from the given cell.
1376
1523
 
1377
- _, known_glossary_guid, valid, _ = process_element_identifiers(egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt,
1378
- EXISTS_REQUIRED, None)
1524
+ :param txt: A string representing the input cell to be processed for
1525
+ extracting glossary-related attributes.
1526
+ :param directive: an optional string indicating the directive to be used - display, validate or execute
1527
+ :return: A string summarizing the outcome of the processing.
1528
+ """
1529
+ command = extract_command(txt)
1530
+ object = command.split()
1531
+ object_type = f"{object[1]} {object[2]}"
1532
+ object_action = object[0]
1533
+ set_debug_level(directive)
1379
1534
 
1380
- print(Markdown(f"{pre_command} `{command}` for glossary:`{glossary_name}` with directive: `{directive}`"))
1535
+ project_name = process_simple_attribute(txt, ['Project Name'])
1536
+ description = process_simple_attribute(txt, ['Description'])
1537
+ project_identifier = process_simple_attribute(txt, ['Project Identifier'])
1538
+ project_status = process_simple_attribute(txt, ['Project Status'])
1539
+ project_phase = process_simple_attribute(txt, ['Project Phase'])
1540
+ project_health = process_simple_attribute(txt, ['Project Health'])
1541
+ start_date = process_simple_attribute(txt, ['Start Date'])
1542
+ planned_end_date = process_simple_attribute(txt, ['Planned End Date'])
1543
+ print(Markdown(f"{pre_command} `\'{command}\'` for project: `{project_name}` with directive: `{directive}` "))
1381
1544
 
1382
- output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1545
+ project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
1546
+ f"* Status: {project_status}\n\t* Description: {description}\n\t"
1547
+ f"* Phase: {project_phase}\n\t* Health: {project_health}\n\t"
1548
+ f"* Start Date: {start_date}\n\t* Planned End Date: {planned_end_date}\n")
1549
+
1550
+ def validate_project(obj_action: str) -> tuple[bool, bool, str, str]:
1551
+ valid = True
1552
+ msg = ""
1553
+ known_guid = None
1554
+ known_q_name = None
1555
+
1556
+ project_details = egeria_client.get_projects_by_name(project_name)
1557
+ if project_details == NO_PROJECTS_FOUND:
1558
+ project_exists = False
1559
+ else:
1560
+ project_exists = True
1561
+
1562
+ if project_name is None:
1563
+ msg = f"* {ERROR}Project name is missing\n"
1564
+ valid = False
1565
+ if project_status is None:
1566
+ msg += f"* {INFO}No Project status found\n"
1567
+
1568
+ if description is None:
1569
+ msg += f"* {INFO}No Description found\n"
1570
+
1571
+ if project_identifier is None:
1572
+ msg += f"* {INFO}No Project Identifier found\n"
1573
+
1574
+ if project_phase is None:
1575
+ msg += f"* {INFO}No Project Phase found\n"
1576
+
1577
+ if project_health is None:
1578
+ msg += f"* {INFO}No Project Health found\n"
1579
+
1580
+ if start_date is None:
1581
+ msg += f"* {INFO}No Start Date found\n"
1582
+ elif not is_valid_iso_date(start_date):
1583
+ msg += f"* {ERROR}Start Date is not a valid ISO date of form YYYY-MM-DD\n"
1584
+ valid = False
1585
+
1586
+ if planned_end_date is None:
1587
+ msg += f"* {INFO} No Planned End Date found\n"
1588
+ elif not is_valid_iso_date(planned_end_date):
1589
+ msg += f"* {ERROR}Planned End Date is not a valid ISO date of form YYYY-MM-DD\n"
1590
+ valid = False
1591
+
1592
+ if obj_action == "Update":
1593
+ q_name = process_simple_attribute(txt, 'Qualified Name')
1594
+
1595
+ if not project_exists:
1596
+ msg += f"* {ERROR}Project {project_name} does not exist\n"
1597
+ valid = False
1598
+ if len(project_details) > 1 and project_exists:
1599
+ msg += f"* {ERROR}More than one project with name {project_name} found\n"
1600
+ valid = False
1601
+ if len(project_details) == 1:
1602
+ known_guid = project_details[0]['elementHeader'].get('guid', None)
1603
+ known_q_name = project_details[0]['glossaryProperties'].get('qualifiedName', None)
1604
+ if q_name is None:
1605
+ msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
1606
+ valid = True
1607
+ elif q_name != known_q_name:
1608
+ msg += (f"* {ERROR}Project {project_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
1609
+ valid = False
1610
+ if valid:
1611
+ msg += project_display
1612
+ msg += f"* -->Project {project_name} exists and can be updated\n"
1613
+ else:
1614
+ msg += f"* --> validation failed\n"
1615
+ msg += '---'
1616
+ print(Markdown(msg))
1617
+ return valid, project_exists, known_guid, known_q_name
1618
+
1619
+ elif obj_action == "Create":
1620
+ if project_exists:
1621
+ msg += f"\n{ERROR}Project {project_name} already exists"
1622
+ else:
1623
+ msg += f"\n-->It is valid to create Project \'{project_name}\' with:\n"
1624
+ print(Markdown(msg))
1625
+ return valid, project_exists, known_guid, known_q_name
1626
+
1627
+ if directive == "display":
1628
+ print(Markdown(project_display))
1629
+ return None
1630
+
1631
+ elif directive == "validate":
1632
+ is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1633
+ valid = is_valid if is_valid else None
1634
+ return valid
1635
+
1636
+ elif directive == "process":
1637
+ is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1638
+ if not is_valid:
1639
+ return None
1640
+ if object_action == "Update":
1641
+ if not exists:
1642
+ print(f"\n\n-->Project {project_name} does not exist")
1643
+ return None
1644
+
1645
+ egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name, description,
1646
+ project_status, project_phase, project_health, start_date, planned_end_date,
1647
+ False)
1648
+ print_msg(ALWAYS, f"Updated Project `{project_name}` with GUID {known_guid}", debug_level)
1649
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1650
+ elif object_action == "Create":
1651
+ guid = None
1652
+ if exists:
1653
+ print(f"Project `{project_name}` already exists and update document created")
1654
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1655
+ else:
1656
+ guid = egeria_client.create_project(None, None, None, False, project_name, description,
1657
+ "PersonalProject", project_identifier, True, project_status,
1658
+ project_phase, project_health, start_date, planned_end_date)
1659
+ project_g = egeria_client.get_project_by_guid(guid)
1660
+ if project_g == NO_GLOSSARIES_FOUND:
1661
+ print(f"Just created with GUID {guid} but Project not found")
1662
+ return None
1663
+
1664
+ q_name = project_g['projectProperties']["qualifiedName"]
1665
+ update_element_dictionary(q_name, {'guid': guid, 'display_name': project_name})
1666
+ print_msg(ALWAYS, f"Created project `{project_name}` with GUID {guid}", debug_level)
1667
+ return update_a_command(txt, command, object_type, q_name, guid)
1668
+
1669
+
1670
+ def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1671
+ """ List terms as a markdown table. Filter based on optional search string. """
1672
+ set_debug_level(directive)
1673
+ valid = True
1674
+ command = extract_command(txt)
1675
+
1676
+ search_string = process_simple_attribute(txt, SEARCH_LABELS)
1677
+ if search_string is None:
1678
+ search_string = '*'
1679
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1680
+
1681
+ glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1682
+ if glossary is not None:
1683
+ _, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
1684
+ msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
1685
+ print_msg(INFO, msg, debug_level)
1686
+ else:
1687
+ glossary_guid = None
1688
+ msg = f"No glossary found"
1689
+ print_msg(INFO, msg, debug_level)
1690
+
1691
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS)
1383
1692
  if output_format is None:
1384
- output_format = "MD"
1385
- elif output_format not in ["DICT", "LIST", "MD"]:
1693
+ output_format = "LIST"
1694
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
1386
1695
  valid = False
1387
1696
  print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1388
1697
 
1389
- request_display = f"\n\t* Glossary name: {glossary_name}\n\t* Output Format: {output_format}\n"
1698
+ request_display = (f"\n\t* Search String: {search_string}\n\t* Glossary: {glossary}\n\t* Output Format: "
1699
+ f"{output_format}\n")
1390
1700
 
1391
1701
  if directive == "display":
1392
1702
  print(Markdown(request_display))
1393
1703
  return None
1394
1704
  elif directive == "validate":
1395
1705
  print(Markdown(request_display))
1396
- return str(valid)
1706
+ return valid
1397
1707
  elif directive == "process":
1398
1708
  try:
1399
1709
  print(Markdown(request_display))
1400
1710
  if not valid: # First validate the term before we process it
1401
1711
  return None
1402
1712
 
1403
- glossary_structure_md = f"\n# Glossary Structure for `{glossary_name}`\n\n"
1713
+ term_list_md = f"\n# Term List for search string: `{search_string}`\n\n"
1404
1714
  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"
1715
+ struct = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
1716
+ term_list_md += f"```{json.dumps(struct, indent=4)}```\n"
1407
1717
  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)
1718
+ term_list_md += egeria_client.find_glossary_terms(search_string, glossary_guid,
1719
+ output_format=output_format)
1720
+ print_msg("ALWAYS", f"Wrote Term List for search string: `{search_string}`", debug_level)
1410
1721
 
1411
- return glossary_structure_md
1722
+ return term_list_md
1723
+
1724
+ md_table = egeria_client.find_glossary_terms(search_string, glossary_guid, output_format=output_format)
1725
+
1726
+ print_msg("ALWAYS", f"Wrote Term list for search string `{search_string}`", debug_level)
1727
+ return md_table
1412
1728
 
1413
1729
  except Exception as e:
1414
1730
  print(f"{ERROR}Error performing {command}: {e}")
@@ -1418,7 +1734,7 @@ def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, dire
1418
1734
  return None
1419
1735
 
1420
1736
 
1421
- def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1737
+ def process_category_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1422
1738
  """ List terms as a markdown table. Filter based on optional search string. """
1423
1739
  set_debug_level(directive)
1424
1740
  valid = True
@@ -1428,8 +1744,6 @@ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive
1428
1744
  if search_string is None:
1429
1745
  search_string = '*'
1430
1746
  print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1431
- if search_string is None:
1432
- search_string = '*'
1433
1747
 
1434
1748
  output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1435
1749
  if output_format is None:
@@ -1441,82 +1755,82 @@ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive
1441
1755
  request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
1442
1756
 
1443
1757
  if directive == "display":
1444
- print(request_display)
1758
+ print(Markdown(request_display))
1445
1759
  return None
1446
1760
  elif directive == "validate":
1447
- print(request_display)
1761
+ print(Markdown(request_display))
1448
1762
  return valid
1449
1763
  elif directive == "process":
1450
1764
  try:
1451
- print(request_display)
1765
+ print(Markdown(request_display))
1452
1766
  if not valid: # First validate the term before we process it
1453
1767
  return None
1454
1768
 
1455
- glossary_list_md = f"\n# Glossary List for `{search_string}`\n\n"
1769
+ cat_list_md = f"\n# Category List for search string: `{search_string}`\n\n"
1456
1770
  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"
1771
+ struct = egeria_client.find_glossary_categories(search_string, output_format=output_format)
1772
+ cat_list_md += f"```{json.dumps(struct, indent=4)}```\n"
1459
1773
  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)
1774
+ cat_list_md += egeria_client.find_glossary_categories(search_string, output_format=output_format)
1775
+ print_msg("ALWAYS", f"Wrote Category List for search string: `{search_string}`", debug_level)
1462
1776
 
1463
- return glossary_list_md
1777
+ return cat_list_md
1464
1778
 
1465
1779
  except Exception as e:
1466
1780
  print(f"{ERROR}Error performing {command}: {e}")
1467
1781
  console.print_exception(show_locals=True)
1468
1782
  return None
1469
1783
  else:
1784
+
1470
1785
  return None
1471
1786
 
1472
1787
 
1473
- def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1788
+ def process_glossary_structure_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1474
1789
  """ List terms as a markdown table. Filter based on optional search string. """
1475
1790
  set_debug_level(directive)
1476
1791
  valid = True
1477
1792
  command = extract_command(txt)
1478
- object_type = command.split(' ')[1].strip()
1479
- object_action = command.split(' ')[0].strip()
1480
1793
 
1481
- element_labels = TERM_NAME_LABELS
1482
- element_labels.append('Display Name')
1794
+ known_glossary_guid = ""
1483
1795
 
1484
- term_name = process_simple_attribute(txt, element_labels, "ERROR")
1796
+ glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, "ERROR")
1485
1797
 
1486
- known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1487
- element_labels, txt, object_action, )
1798
+ _, known_glossary_guid, valid, _ = process_element_identifiers(egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt,
1799
+ EXISTS_REQUIRED, None)
1488
1800
 
1489
- print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1801
+ print(Markdown(f"{pre_command} `{command}` for glossary:`{glossary_name}` with directive: `{directive}`"))
1490
1802
 
1491
1803
  output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1492
1804
  if output_format is None:
1493
- output_format = "LIST"
1494
- elif output_format not in ["DICT", "LIST"]:
1805
+ output_format = "MD"
1806
+ elif output_format not in ["DICT", "LIST", "MD"]:
1495
1807
  valid = False
1496
1808
  print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1497
1809
 
1498
- request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format {output_format}\n\t* GUID: {known_guid}\n"
1810
+ request_display = f"\n\t* Glossary name: {glossary_name}\n\t* Output Format: {output_format}\n"
1499
1811
 
1500
1812
  if directive == "display":
1501
- print(request_display)
1813
+ print(Markdown(request_display))
1502
1814
  return None
1503
1815
  elif directive == "validate":
1504
- print(request_display)
1505
- return valid
1816
+ print(Markdown(request_display))
1817
+ return str(valid)
1506
1818
  elif directive == "process":
1507
1819
  try:
1508
- print(request_display)
1820
+ print(Markdown(request_display))
1509
1821
  if not valid: # First validate the term before we process it
1510
1822
  return None
1511
- term_history_md = f"\n# Term History for `{term_name}`\n\n"
1823
+
1824
+ glossary_structure_md = f"\n# Glossary Structure for `{glossary_name}`\n\n"
1512
1825
  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"
1826
+ struct = egeria_client.get_glossary_category_structure(known_glossary_guid, output_format=output_format)
1827
+ glossary_structure_md += f"```{json.dumps(struct, indent=4)}```\n"
1515
1828
  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)
1829
+ glossary_structure_md += egeria_client.get_glossary_category_structure(known_glossary_guid,
1830
+ output_format=output_format)
1831
+ print_msg("ALWAYS", f"Wrote Glossary Structure for glossary: `{glossary_name}`", debug_level)
1518
1832
 
1519
- return term_history_md
1833
+ return glossary_structure_md
1520
1834
 
1521
1835
  except Exception as e:
1522
1836
  print(f"{ERROR}Error performing {command}: {e}")
@@ -1526,52 +1840,49 @@ def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive:
1526
1840
  return None
1527
1841
 
1528
1842
 
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."""
1843
+ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1844
+ """ List terms as a markdown table. Filter based on optional search string. """
1532
1845
  set_debug_level(directive)
1533
1846
  valid = True
1534
1847
  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
1848
 
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}` "))
1849
+ search_string = process_simple_attribute(txt, SEARCH_LABELS, "INFO")
1850
+ if search_string is None:
1851
+ search_string = '*'
1852
+ print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1853
+ if search_string is None:
1854
+ search_string = '*'
1544
1855
 
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')
1856
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1548
1857
  if output_format is None:
1549
1858
  output_format = "LIST"
1550
- elif output_format not in ["DICT", "LIST", "MD"]:
1859
+ elif output_format not in ELEMENT_OUTPUT_FORMATS:
1551
1860
  valid = False
1552
1861
  print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1553
1862
 
1554
- request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format: {output_format}\n"
1863
+ request_display = f"\n\t* Search String: {search_string}\n\t* Output Format: {output_format}\n"
1555
1864
 
1556
1865
  if directive == "display":
1557
1866
  print(request_display)
1558
1867
  return None
1559
1868
  elif directive == "validate":
1560
1869
  print(request_display)
1561
- return str(valid)
1870
+ return valid
1562
1871
  elif directive == "process":
1563
1872
  try:
1564
1873
  print(request_display)
1565
1874
  if not valid: # First validate the term before we process it
1566
1875
  return None
1567
- term_history_md = f"\n# Term Revision History for `{term_name}`\n\n"
1876
+
1877
+ glossary_list_md = f"\n# Glossary List for `{search_string}`\n\n"
1568
1878
  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"
1879
+ struct = egeria_client.find_glossaries(search_string, output_format=output_format)
1880
+ glossary_list_md += f"```{json.dumps(struct, indent=4)}```\n"
1571
1881
  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
1882
+ glossary_list_md += egeria_client.find_glossaries(search_string, output_format=output_format)
1883
+ print_msg("ALWAYS", f"Wrote Glossary List for search string: `{search_string}`", debug_level)
1884
+
1885
+ return glossary_list_md
1575
1886
 
1576
1887
  except Exception as e:
1577
1888
  print(f"{ERROR}Error performing {command}: {e}")
@@ -1581,333 +1892,112 @@ def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, d
1581
1892
  return None
1582
1893
 
1583
1894
 
1584
- def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1585
- """
1586
- Processes a term create or update command by extracting key attributes such as
1587
- term name, summary, description, abbreviation, examples, usage, version, and status from the given cell.
1588
-
1589
- :param txt: A string representing the input cell to be processed for
1590
- extracting glossary-related attributes.
1591
- :param directive: an optional string indicating the directive to be used - display, validate or execute
1592
- :return: A string summarizing the outcome of the processing.
1593
- """
1594
- valid = True
1595
- categories_list = None
1596
- cats_exist = True
1895
+ def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1896
+ """ List terms as a markdown table. Filter based on optional search string. """
1597
1897
  set_debug_level(directive)
1598
- known_q_name = None
1898
+ valid = True
1599
1899
  command = extract_command(txt)
1600
1900
  object_type = command.split(' ')[1].strip()
1601
1901
  object_action = command.split(' ')[0].strip()
1602
1902
 
1603
- term_name = process_simple_attribute(txt, ['Term Name', 'Display Name'], ERROR)
1604
- print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1605
- summary = process_simple_attribute(txt, ['Summary'])
1606
- description = process_simple_attribute(txt, ['Description'])
1607
- abbreviation = process_simple_attribute(txt, ['Abbreviation'])
1608
- examples = process_simple_attribute(txt, ['Examples'])
1609
- usage = process_simple_attribute(txt, ['Usage'])
1610
- status = process_simple_attribute(txt, ['Status'])
1611
- status = status.upper() if status else 'DRAFT'
1612
- version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"])
1613
- q_name = process_simple_attribute(txt, ['Qualified Name'])
1903
+ element_labels = TERM_NAME_LABELS
1904
+ element_labels.append('Display Name')
1614
1905
 
1615
- # validate term name and get existing qualified_name and guid if they exist
1616
- if term_name is None:
1617
- valid = False
1618
- known_q_name, known_guid, term_exists = None
1619
- else:
1620
- element_labels = TERM_NAME_LABELS
1621
- element_labels.append('Display Name')
1622
- known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1623
- element_labels, txt, object_action,
1624
- version)
1906
+ term_name = process_simple_attribute(txt, element_labels, "ERROR")
1625
1907
 
1626
- # get the glossary qualified name this term is in
1627
- glossary_name = process_simple_attribute(txt, GLOSSARY_NAME_LABELS, ERROR)
1628
- if glossary_name is None:
1629
- valid = False
1630
- known_glossary_guid = None
1631
- known_glossary_q_name = None
1632
- glossary_valid = False
1633
- glossary_exists = False
1634
- else:
1635
- known_glossary_q_name, known_glossary_guid, glossary_valid, glossary_exists = process_element_identifiers(
1636
- egeria_client, "Glossary", GLOSSARY_NAME_LABELS, txt, EXISTS_REQUIRED, None)
1908
+ known_q_name, known_guid, valid, term_exists = process_element_identifiers(egeria_client, object_type,
1909
+ element_labels, txt, object_action, )
1637
1910
 
1638
- # process categories, if present
1639
- categories = process_simple_attribute(txt, ['Glossary Categories', 'Glossary Category', 'Category', 'Categories'])
1640
- if categories: # Find information about categoriess that classify this term
1641
- msg = "Checking for categories that classify this term"
1642
- print_msg("DEBUG-INFO", msg, debug_level)
1643
- categories_list, cat_q_name_list, cat_valid, cat_exist = process_name_list(egeria_client, 'Glossary Categories',
1644
- txt, CATEGORY_NAME_LABELS)
1645
- if cat_exist and cat_valid:
1646
- msg = f"Found valid glossary categories to classify the term:\n\t{term_name}"
1647
- print_msg("INFO", msg, debug_level)
1648
- else:
1649
- msg = "No valid glossary categories found."
1650
- print_msg("INFO", msg, debug_level)
1651
- else:
1652
- cat_exist = cat_valid = False
1653
- cat_q_name_list = None
1911
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_name}` with directive: `{directive}`"))
1654
1912
 
1655
- if object_action == "Update": # check to see if provided information exists and is consistent with existing info
1656
- term_guid = process_simple_attribute(txt, GUID_LABELS)
1657
- update_description = process_simple_attribute(txt, ['Update Description'])
1658
- term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1659
- f"* Term Name: {term_name}\n\t* Qualified Name: {q_name}\n\t* Categories: {categories}\n\t"
1660
- f"* Summary: {summary}\n\t* Description: {description}\n\t"
1661
- f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1662
- f"* Version: {version}\n\t* Status: {status}\n\t* GUID: {term_guid}"
1663
- f"\n\t* Update Description: {update_description}\n")
1664
- if not term_exists:
1665
- msg = f"Update request invalid, Term {term_name} does not exist\n"
1666
- print_msg(ERROR, msg, debug_level)
1667
- valid = False
1913
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1914
+ if output_format is None:
1915
+ output_format = "LIST"
1916
+ elif output_format not in ["DICT", "LIST"]:
1917
+ valid = False
1918
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1668
1919
 
1669
- elif object_action == 'Create': # if the command is create, check that it doesn't already exist
1670
- term_display = (f"\n* Command: {command}\n\t* Glossary: {known_glossary_q_name}\n\t"
1671
- f"* Term Name: {term_name}\n\t* Categories: {categories}\n\t* Summary: {summary}\n\t"
1672
- f"* Qualified Name: {q_name}\n\t* Description: {description}\n\t"
1673
- f"* Abbreviation: {abbreviation}\n\t* Examples: {examples}\n\t* Usage: {usage}\n\t"
1674
- f"* Version: {version}\n\t* Status: {status}\n")
1675
- if term_exists:
1676
- msg = f"Term `{term_name}` cannot be created since it already exists\n"
1677
- print_msg(ERROR, msg, debug_level)
1678
- else:
1679
- msg = f"It is valid to create Term `{term_name}`"
1680
- print_msg(ALWAYS, msg, debug_level)
1920
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format {output_format}\n\t* GUID: {known_guid}\n"
1681
1921
 
1682
1922
  if directive == "display":
1683
- print(Markdown(term_display))
1923
+ print(request_display)
1684
1924
  return None
1685
1925
  elif directive == "validate":
1686
- print(Markdown(term_display))
1926
+ print(request_display)
1687
1927
  return valid
1688
1928
  elif directive == "process":
1689
1929
  try:
1930
+ print(request_display)
1690
1931
  if not valid: # First validate the term before we process it
1691
1932
  return None
1692
- print(Markdown(term_display))
1693
- if object_action == "Update" and directive == "process":
1694
- if not term_exists:
1695
- return None
1696
- body = {
1697
- "class": "ReferenceableRequestBody", "elementProperties": {
1698
- "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "summary": summary,
1699
- "description": description, "abbreviation": abbreviation, "examples": examples, "usage": usage,
1700
- "publishVersionIdentifier": version, "status": status
1701
- }, "updateDescription": update_description
1702
- }
1703
- egeria_client.update_term(known_guid, body_slimmer(body))
1704
- # if cat_exist and cat_valid:
1705
- update_term_categories(egeria_client, known_guid, cats_exist, cat_q_name_list)
1706
- print_msg(ALWAYS,
1707
- f"\tUpdated Term `{term_name}` with GUID {known_guid}\n\tand categories `{categories}`",
1708
- debug_level)
1709
- return egeria_client.get_term_by_guid(known_guid,
1710
- 'md') # return update_a_command(txt, command, object_type,
1711
- # known_q_name, known_guid)
1712
- elif object_action == "Update" and directive == "validate": # is sthis reachable?
1713
- return egeria_client.get_term_by_guid(known_guid, 'md')
1933
+ term_history_md = f"\n# Term History for `{term_name}`\n\n"
1934
+ if output_format == "DICT":
1935
+ struct = egeria_client.list_term_revision_history(known_guid, output_format=output_format)
1936
+ term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
1937
+ else:
1938
+ term_history_md += egeria_client.list_full_term_history(known_guid, output_format)
1939
+ print_msg("ALWAYS", f"Wrote Term History for term `{term_name}`", debug_level)
1714
1940
 
1715
- elif object_action == "Create":
1716
- if term_exists:
1717
- msg = f"Term {term_name} exists so result document modifies term create to term update"
1718
- print_msg(INFO, msg, debug_level)
1719
- return update_a_command(txt, command, object_type, q_name, known_guid)
1720
- else:
1721
- ## get the guid for the glossary from the name - first look in cache
1722
- cached = get_element_dictionary().get(known_glossary_q_name, None)
1941
+ return term_history_md
1723
1942
 
1724
- if cached is not None:
1725
- glossary_guid = cached.get('guid', None)
1726
- if glossary_guid is None:
1727
- msg = f"Glossary GUID for {known_glossary_q_name} not found in cache"
1728
- print_msg(WARNING, msg, debug_level) # should this ever occur?
1729
- return None
1730
- else:
1731
- glossary_guid = egeria_client.__get_guid__(qualified_name=known_glossary_q_name)
1732
- if glossary_guid == NO_ELEMENTS_FOUND:
1733
- msg = f"Glossary {known_glossary_q_name} not found"
1734
- print_msg(WARNING, msg, debug_level)
1735
- return None
1736
- term_body = {
1737
- "class": "ReferenceableRequestBody", "elementProperties": {
1738
- "class": "GlossaryTermProperties", "qualifiedName": known_q_name, "displayName": term_name,
1739
- "summary": summary, "description": description, "abbreviation": abbreviation,
1740
- "examples": examples, "usage": usage, "publishVersionIdentifier": version
1741
- # "additionalProperties":
1742
- # {
1743
- # "propertyName1": "xxxx",
1744
- # "propertyName2": "xxxx"
1745
- # }
1746
- }, "initialStatus": status
1747
- }
1748
- term_guid = egeria_client.create_controlled_glossary_term(glossary_guid, body_slimmer(term_body))
1749
- if term_guid == NO_ELEMENTS_FOUND:
1750
- print(f"{ERROR}Term {term_name} not created")
1751
- return None
1752
- if cats_exist and categories is not None:
1753
- update_term_categories(egeria_client, term_guid, cats_exist, cat_q_name_list)
1754
- update_element_dictionary(known_q_name, {'guid': term_guid, 'display_name': term_name})
1755
- print_msg(ALWAYS, f"Created term `{term_name}` with GUID {term_guid}", debug_level)
1756
- return egeria_client.get_term_by_guid(term_guid,
1757
- 'MD') # return update_a_command(txt, command,
1758
- # object_type, q_name, term_guid)
1759
1943
  except Exception as e:
1760
- print(f"{ERROR}Error creating term {term_name}: {e}")
1944
+ print(f"{ERROR}Error performing {command}: {e}")
1761
1945
  console.print_exception(show_locals=True)
1762
1946
  return None
1947
+ else:
1948
+ return None
1763
1949
 
1764
1950
 
1765
- def process_per_proj_upsert_command(egeria_client: ProjectManager, txt: str, directive: str = "display") -> str | None:
1766
- """
1767
- Processes a personal project create or update command by extracting key attributes such as
1768
- glossary name, language, description, and usage from the given cell.
1769
-
1770
- :param txt: A string representing the input cell to be processed for
1771
- extracting glossary-related attributes.
1772
- :param directive: an optional string indicating the directive to be used - display, validate or execute
1773
- :return: A string summarizing the outcome of the processing.
1774
- """
1775
- command = extract_command(txt)
1776
- object = command.split()
1777
- object_type = f"{object[1]} {object[2]}"
1778
- object_action = object[0]
1951
+ def process_term_revision_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1952
+ """ List term revision history as a markdown table or list."""
1779
1953
  set_debug_level(directive)
1954
+ valid = True
1955
+ command = extract_command(txt)
1956
+ object_type = command.split(' ')[1].strip()
1957
+ object_action = command.split(' ')[0].strip()
1958
+ known_q_name = None
1959
+ known_guid = None
1780
1960
 
1781
- project_name = process_simple_attribute(txt, ['Project Name'])
1782
- description = process_simple_attribute(txt, ['Description'])
1783
- project_identifier = process_simple_attribute(txt, ['Project Identifier'])
1784
- project_status = process_simple_attribute(txt, ['Project Status'])
1785
- project_phase = process_simple_attribute(txt, ['Project Phase'])
1786
- project_health = process_simple_attribute(txt, ['Project Health'])
1787
- start_date = process_simple_attribute(txt, ['Start Date'])
1788
- planned_end_date = process_simple_attribute(txt, ['Planned End Date'])
1789
- print(Markdown(f"{pre_command} `\'{command}\'` for project: `{project_name}` with directive: `{directive}` "))
1790
-
1791
- project_display = (f"\n* Command: {command}\n\t* Project: {project_name}\n\t"
1792
- f"* Status: {project_status}\n\t* Description: {description}\n\t"
1793
- f"* Phase: {project_phase}\n\t* Health: {project_health}\n\t"
1794
- f"* Start Date: {start_date}\n\t* Planned End Date: {planned_end_date}\n")
1795
-
1796
- def validate_project(obj_action: str) -> tuple[bool, bool, str, str]:
1797
- valid = True
1798
- msg = ""
1799
- known_guid = None
1800
- known_q_name = None
1801
-
1802
- project_details = egeria_client.get_projects_by_name(project_name)
1803
- if project_details == NO_PROJECTS_FOUND:
1804
- project_exists = False
1805
- else:
1806
- project_exists = True
1807
-
1808
- if project_name is None:
1809
- msg = f"* {ERROR}Project name is missing\n"
1810
- valid = False
1811
- if project_status is None:
1812
- msg += f"* {INFO}No Project status found\n"
1813
-
1814
- if description is None:
1815
- msg += f"* {INFO}No Description found\n"
1816
-
1817
- if project_identifier is None:
1818
- msg += f"* {INFO}No Project Identifier found\n"
1819
-
1820
- if project_phase is None:
1821
- msg += f"* {INFO}No Project Phase found\n"
1822
-
1823
- if project_health is None:
1824
- msg += f"* {INFO}No Project Health found\n"
1825
-
1826
- if start_date is None:
1827
- msg += f"* {INFO}No Start Date found\n"
1828
- elif not is_valid_iso_date(start_date):
1829
- msg += f"* {ERROR}Start Date is not a valid ISO date of form YYYY-MM-DD\n"
1830
- valid = False
1831
-
1832
- if planned_end_date is None:
1833
- msg += f"* {INFO} No Planned End Date found\n"
1834
- elif not is_valid_iso_date(planned_end_date):
1835
- msg += f"* {ERROR}Planned End Date is not a valid ISO date of form YYYY-MM-DD\n"
1836
- valid = False
1961
+ element_labels = TERM_NAME_LABELS
1837
1962
 
1838
- if obj_action == "Update":
1839
- q_name = process_simple_attribute(txt, 'Qualified Name')
1963
+ term_name = process_simple_attribute(txt, element_labels, "ERROR")
1964
+ print(Markdown(f"{pre_command} `{command}` for term: `{term_name}` with directive: `{directive}` "))
1840
1965
 
1841
- if not project_exists:
1842
- msg += f"* {ERROR}Project {project_name} does not exist\n"
1843
- valid = False
1844
- if len(project_details) > 1 and project_exists:
1845
- msg += f"* {ERROR}More than one project with name {project_name} found\n"
1846
- valid = False
1847
- if len(project_details) == 1:
1848
- known_guid = project_details[0]['elementHeader'].get('guid', None)
1849
- known_q_name = project_details[0]['glossaryProperties'].get('qualifiedName', None)
1850
- if q_name is None:
1851
- msg += f"* {INFO}Qualified Name is missing => can use known qualified name of {known_q_name}\n"
1852
- valid = True
1853
- elif q_name != known_q_name:
1854
- msg += (f"* {ERROR}Project {project_name} qualifiedName mismatch between {q_name} and {known_q_name}\n")
1855
- valid = False
1856
- if valid:
1857
- msg += project_display
1858
- msg += f"* -->Project {project_name} exists and can be updated\n"
1859
- else:
1860
- msg += f"* --> validation failed\n"
1861
- msg += '---'
1862
- print(Markdown(msg))
1863
- return valid, project_exists, known_guid, known_q_name
1966
+ known_q_name, known_guid, valid, _ = process_element_identifiers(egeria_client, object_type, element_labels, txt,
1967
+ object_action, )
1968
+ output_format = process_simple_attribute(txt, ['Output Format', 'Format'], 'INFO')
1969
+ if output_format is None:
1970
+ output_format = "LIST"
1971
+ elif output_format not in ["DICT", "LIST", "MD"]:
1972
+ valid = False
1973
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1864
1974
 
1865
- elif obj_action == "Create":
1866
- if project_exists:
1867
- msg += f"\n{ERROR}Project {project_name} already exists"
1868
- else:
1869
- msg += f"\n-->It is valid to create Project \'{project_name}\' with:\n"
1870
- print(Markdown(msg))
1871
- return valid, project_exists, known_guid, known_q_name
1975
+ request_display = f"\n\t* Term Name: {term_name}\n\t* Output Format: {output_format}\n"
1872
1976
 
1873
1977
  if directive == "display":
1874
- print(Markdown(project_display))
1978
+ print(request_display)
1875
1979
  return None
1876
-
1877
1980
  elif directive == "validate":
1878
- is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1879
- valid = is_valid if is_valid else None
1880
- return valid
1881
-
1981
+ print(request_display)
1982
+ return str(valid)
1882
1983
  elif directive == "process":
1883
- is_valid, exists, known_guid, known_q_name = validate_project(object_action)
1884
- if not is_valid:
1885
- return None
1886
- if object_action == "Update":
1887
- if not exists:
1888
- print(f"\n\n-->Project {project_name} does not exist")
1984
+ try:
1985
+ print(request_display)
1986
+ if not valid: # First validate the term before we process it
1889
1987
  return None
1890
-
1891
- egeria_client.update_project(known_guid, known_q_name, project_identifier, project_name, description,
1892
- project_status, project_phase, project_health, start_date, planned_end_date,
1893
- False)
1894
- print_msg(ALWAYS, f"Updated Project `{project_name}` with GUID {known_guid}", debug_level)
1895
- return update_a_command(txt, command, object_type, known_q_name, known_guid)
1896
- elif object_action == "Create":
1897
- guid = None
1898
- if exists:
1899
- print(f"Project `{project_name}` already exists and update document created")
1900
- return update_a_command(txt, command, object_type, known_q_name, known_guid)
1988
+ term_history_md = f"\n# Term Revision History for `{term_name}`\n\n"
1989
+ if output_format == "DICT":
1990
+ struct = egeria_client.list_term_revision_history(known_guid, output_format)
1991
+ term_history_md += f"```{json.dumps(struct, indent=4)}```\n"
1901
1992
  else:
1902
- guid = egeria_client.create_project(None, None, None, False, project_name, description,
1903
- "PersonalProject", project_identifier, True, project_status,
1904
- project_phase, project_health, start_date, planned_end_date)
1905
- project_g = egeria_client.get_project_by_guid(guid)
1906
- if project_g == NO_GLOSSARIES_FOUND:
1907
- print(f"Just created with GUID {guid} but Project not found")
1908
- return None
1993
+ term_history_md += egeria_client.list_term_revision_history(known_guid, output_format)
1994
+ print_msg("ALWAYS", f"Wrote Term Revision History for term `{term_name}`", debug_level)
1995
+ return term_history_md
1996
+
1997
+ except Exception as e:
1998
+ print(f"{ERROR}Error performing {command}: {e}")
1999
+ console.print_exception(show_locals=True)
2000
+ return None
2001
+ else:
2002
+ return None
1909
2003
 
1910
- q_name = project_g['projectProperties']["qualifiedName"]
1911
- update_element_dictionary(q_name, {'guid': guid, 'display_name': project_name})
1912
- print_msg(ALWAYS, f"Created project `{project_name}` with GUID {guid}", debug_level)
1913
- return update_a_command(txt, command, object_type, q_name, guid)