pyegeria 5.3.8.10__py3-none-any.whl → 5.3.9.1__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.
pyegeria/__init__.py CHANGED
@@ -64,7 +64,7 @@ from .md_processing_utils import (extract_command, process_glossary_upsert_comma
64
64
  process_glossary_list_command, process_category_list_command,
65
65
  process_term_history_command, process_glossary_structure_command,
66
66
  process_term_revision_history_command, process_create_term_term_relationship_command,
67
- )
67
+ process_term_details_command,)
68
68
 
69
69
  #
70
70
  # The following assignments were generated by the `create_tech_guid_lists.py` utility that uses the pyegeria functions
@@ -15,7 +15,7 @@ from pyegeria import (extract_command, process_glossary_upsert_command, process_
15
15
  process_solution_component_upsert_command, dr_egeria_state, process_term_list_command,
16
16
  process_category_list_command, process_glossary_list_command, process_term_history_command,
17
17
  process_glossary_structure_command, process_term_revision_history_command,
18
- process_create_term_term_relationship_command)
18
+ process_create_term_term_relationship_command, process_term_details_command)
19
19
 
20
20
  EGERIA_METADATA_STORE = os.environ.get("EGERIA_METADATA_STORE", "active-metadata-store")
21
21
  EGERIA_KAFKA_ENDPOINT = os.environ.get("KAFKA_ENDPOINT", "localhost:9092")
@@ -97,6 +97,8 @@ def process_markdown_file(file_path: str, directive: str, server: str, url: str,
97
97
  result = process_create_term_term_relationship_command(client, current_block, directive)
98
98
  elif potential_command in ["List Term History", "Term History"]:
99
99
  result = process_term_history_command(client, current_block, directive)
100
+ elif potential_command in ["List Term Details"]:
101
+ result = process_term_details_command(client, current_block, directive)
100
102
  elif potential_command in ["List Term Update History", "List Term Revision History"]:
101
103
  result = process_term_revision_history_command(client, current_block, directive)
102
104
  elif potential_command in ["List Terms", "List Glossary Terms"]:
@@ -150,7 +152,7 @@ def process_markdown_file(file_path: str, directive: str, server: str, url: str,
150
152
  in_h1_block = True
151
153
 
152
154
  # Handle the end of a block (line starts with `---`)
153
- elif line.startswith("---"):
155
+ elif line.startswith("___"):
154
156
  if in_h1_block:
155
157
  # Process the current block when it ends with `---`
156
158
  current_block += f"\n{line}"
@@ -149,7 +149,7 @@ def display_glossary_terms(
149
149
  expand=True,
150
150
  )
151
151
  table.add_column("Term Name / Abbreviation / Version")
152
- table.add_column("Qualified Name / GUID", width=38, no_wrap=True)
152
+ table.add_column("Qualified Name / GUID / Aliases", width=38, no_wrap=True)
153
153
  table.add_column("Summary")
154
154
  table.add_column("Description")
155
155
  table.add_column("Glossary")
@@ -184,8 +184,9 @@ def display_glossary_terms(
184
184
  display_name = props.get("displayName","---")
185
185
  qualified_name = props["qualifiedName"]
186
186
  term_guid = term["elementHeader"]["guid"]
187
+ aliases = props.get("aliases", "---")
187
188
  q_name = Text(
188
- f"{qualified_name}\n&\n{term_guid}", style=style, justify="center"
189
+ f"{qualified_name}\n&\n{term_guid}\n&\n{aliases}", style=style, justify="center"
189
190
  )
190
191
  abbrev = Text(props.get("abbreviation", "---"), style=style, justify="center")
191
192
  summary = Text(props.get("summary", "---"), style=style)
@@ -12,6 +12,7 @@ from datetime import datetime
12
12
 
13
13
  from pyegeria import NO_GLOSSARIES_FOUND, max_paging_size
14
14
  from pyegeria._client import Client
15
+ from pyegeria._exceptions import InvalidParameterException, PropertyServerException, UserNotAuthorizedException
15
16
  from pyegeria._globals import NO_CATEGORIES_FOUND, NO_TERMS_FOUND
16
17
  from pyegeria._validators import validate_guid, validate_name, validate_search_string
17
18
  from pyegeria.utils import body_slimmer
@@ -222,7 +223,8 @@ class GlossaryBrowser(Client):
222
223
  str: Markdown representation
223
224
  """
224
225
  return self._generate_entity_md(elements=elements, elements_action=elements_action, output_format=output_format,
225
- entity_type="Glossary", extract_properties_func=self._extract_glossary_properties)
226
+ entity_type="Glossary",
227
+ extract_properties_func=self._extract_glossary_properties)
226
228
 
227
229
  def _generate_entity_md_table(self, elements: list, search_string: str, entity_type: str, extract_properties_func,
228
230
  columns: list, get_additional_props_func=None, output_format: str = 'LIST') -> str:
@@ -302,14 +304,15 @@ class GlossaryBrowser(Client):
302
304
  str: Markdown table
303
305
  """
304
306
  columns = [{'name': 'Glossary Name', 'key': 'display_name'},
305
- {'name': 'Qualified Name', 'key': 'qualified_name'},
306
- {'name': 'Language', 'key': 'language', 'format': True},
307
- {'name': 'Description', 'key': 'description', 'format': True},
308
- {'name': 'Usage', 'key': 'usage', 'format': True},
309
- {'name': 'Categories', 'key': 'categories_dn_md', 'format': True}, ]
307
+ {'name': 'Qualified Name', 'key': 'qualified_name'},
308
+ {'name': 'Language', 'key': 'language', 'format': True},
309
+ {'name': 'Description', 'key': 'description', 'format': True},
310
+ {'name': 'Usage', 'key': 'usage', 'format': True},
311
+ {'name': 'Categories', 'key': 'categories_dn_md', 'format': True}, ]
310
312
 
311
313
  return self._generate_entity_md_table(elements=elements, search_string=search_string, entity_type="Glossary",
312
- extract_properties_func=self._extract_glossary_properties, columns=columns)
314
+ extract_properties_func=self._extract_glossary_properties,
315
+ columns=columns)
313
316
 
314
317
  def _generate_entity_dict(self, elements: list, extract_properties_func, get_additional_props_func=None,
315
318
  include_keys=None, exclude_keys=None, output_format: str = 'DICT') -> list:
@@ -368,7 +371,7 @@ class GlossaryBrowser(Client):
368
371
  list: List of glossary dictionaries
369
372
  """
370
373
  return self._generate_entity_dict(elements=elements, extract_properties_func=self._extract_glossary_properties,
371
- exclude_keys=['properties', 'categories_qn_md'], output_format=output_format)
374
+ exclude_keys=['properties', 'categories_qn_md'], output_format=output_format)
372
375
 
373
376
  def generate_glossaries_md(self, elements: list | dict, search_string: str,
374
377
  output_format: str = 'MD') -> str | list:
@@ -426,9 +429,9 @@ class GlossaryBrowser(Client):
426
429
  aliases = ", ".join(properties.get("aliases", "")) or ""
427
430
 
428
431
  return {
429
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'aliases': aliases, 'summary': summary,
430
- 'description': description, 'examples': examples, 'usage': usage, 'version identifier': pub_version,
431
- 'qualified_name': qualified_name, 'status': status
432
+ 'guid': guid, 'properties': properties, 'display_name': display_name, 'aliases': aliases,
433
+ 'summary': summary, 'description': description, 'examples': examples, 'usage': usage,
434
+ 'version identifier': pub_version, 'qualified_name': qualified_name, 'status': status
432
435
  }
433
436
 
434
437
  def _get_categories_for_term(self, term_guid: str, output_format: str = None) -> tuple[list, str]:
@@ -449,7 +452,7 @@ class GlossaryBrowser(Client):
449
452
 
450
453
  category_list = self.get_categories_for_term(term_guid)
451
454
  if type(category_list) is str and category_list == NO_CATEGORIES_FOUND:
452
- category_list_md = '---'
455
+ category_list_md = ''
453
456
  elif isinstance(category_list, list) and len(category_list) > 0:
454
457
  first_cat = True
455
458
  for category in category_list:
@@ -507,16 +510,17 @@ class GlossaryBrowser(Client):
507
510
  str: Markdown table
508
511
  """
509
512
  columns = [{'name': 'Term Name', 'key': 'display_name'}, {'name': 'Qualified Name', 'key': 'qualified_name'},
510
- {'name': 'Aliases', 'key': 'aliases', 'format': True}, {'name': 'Summary', 'key': 'summary', 'format': True},
511
- {'name': 'Glossary', 'key': 'glossary'}, {'name': 'Categories', 'key': 'categories_str', 'format': True}]
513
+ {'name': 'Aliases', 'key': 'aliases', 'format': True},
514
+ {'name': 'Summary', 'key': 'summary', 'format': True}, {'name': 'Glossary', 'key': 'glossary'},
515
+ {'name': 'Categories', 'key': 'categories_str', 'format': True}]
512
516
 
513
517
  # Create a wrapper function to pass output_format to _get_term_table_properties
514
518
  def get_table_props_with_format(element, term_guid, output_format_param=None):
515
519
  return self._get_term_table_properties(element, term_guid, output_format)
516
520
 
517
521
  return self._generate_entity_md_table(elements=elements, search_string=search_string, entity_type="Term",
518
- extract_properties_func=self._extract_term_properties, columns=columns,
519
- get_additional_props_func=get_table_props_with_format)
522
+ extract_properties_func=self._extract_term_properties, columns=columns,
523
+ get_additional_props_func=get_table_props_with_format)
520
524
 
521
525
  def _get_term_dict_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
522
526
  """
@@ -558,9 +562,10 @@ class GlossaryBrowser(Client):
558
562
  return self._get_term_dict_properties(element, term_guid, output_format)
559
563
 
560
564
  return self._generate_entity_dict(elements=elements, extract_properties_func=self._extract_term_properties,
561
- get_additional_props_func=get_dict_props_with_format, exclude_keys=['properties', 'pub_version']
562
- # Exclude raw properties and pub_version (renamed to version)
563
- )
565
+ get_additional_props_func=get_dict_props_with_format,
566
+ exclude_keys=['properties', 'pub_version']
567
+ # Exclude raw properties and pub_version (renamed to version)
568
+ )
564
569
 
565
570
  def _get_term_additional_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
566
571
  """
@@ -597,8 +602,8 @@ class GlossaryBrowser(Client):
597
602
  str: Markdown representation
598
603
  """
599
604
  return self._generate_entity_md(elements=elements, elements_action=elements_action, output_format=output_format,
600
- entity_type="Term", extract_properties_func=self._extract_term_properties,
601
- get_additional_props_func=self._get_term_additional_properties)
605
+ entity_type="Term", extract_properties_func=self._extract_term_properties,
606
+ get_additional_props_func=self._get_term_additional_properties)
602
607
 
603
608
  def generate_terms_md(self, elements: list | dict, search_string: str, output_format: str = 'MD') -> str | list:
604
609
  """
@@ -776,17 +781,18 @@ class GlossaryBrowser(Client):
776
781
  str: Markdown table
777
782
  """
778
783
  columns = [{'name': 'Display Name', 'key': 'display_name'},
779
- {'name': 'Description', 'key': 'description', 'format': True},
780
- {'name': 'Qualified Name', 'key': 'qualified_name'}, {'name': 'Parent Category', 'key': 'parent_category'},
781
- {'name': 'Subcategories', 'key': 'subcategories', 'format': True}]
784
+ {'name': 'Description', 'key': 'description', 'format': True},
785
+ {'name': 'Qualified Name', 'key': 'qualified_name'},
786
+ {'name': 'Parent Category', 'key': 'parent_category'},
787
+ {'name': 'Subcategories', 'key': 'subcategories', 'format': True}]
782
788
 
783
789
  # Create a wrapper function to pass output_format to _get_category_table_properties
784
790
  def get_table_props_with_format(element, category_guid, output_format_param=None):
785
791
  return self._get_category_table_properties(element, category_guid, output_format)
786
792
 
787
793
  return self._generate_entity_md_table(elements=elements, search_string=search_string, entity_type="Category",
788
- extract_properties_func=self._extract_category_properties, columns=columns,
789
- get_additional_props_func=get_table_props_with_format)
794
+ extract_properties_func=self._extract_category_properties,
795
+ columns=columns, get_additional_props_func=get_table_props_with_format)
790
796
 
791
797
  def _get_category_dict_properties(self, element: dict, category_guid: str, output_format: str = None) -> dict:
792
798
  """
@@ -830,8 +836,9 @@ class GlossaryBrowser(Client):
830
836
  return self._get_category_dict_properties(element, category_guid, output_format)
831
837
 
832
838
  return self._generate_entity_dict(elements=elements, extract_properties_func=self._extract_category_properties,
833
- get_additional_props_func=get_dict_props_with_format, exclude_keys=['properties'], # Exclude raw properties
834
- output_format=output_format)
839
+ get_additional_props_func=get_dict_props_with_format,
840
+ exclude_keys=['properties'], # Exclude raw properties
841
+ output_format=output_format)
835
842
 
836
843
  def _get_category_additional_properties(self, element: dict, category_guid: str, output_format: str = None) -> dict:
837
844
  """
@@ -882,8 +889,9 @@ class GlossaryBrowser(Client):
882
889
  return self._get_category_additional_properties(element, category_guid, output_format)
883
890
 
884
891
  return self._generate_entity_md(elements=elements, elements_action=elements_action, output_format=output_format,
885
- entity_type="Category", extract_properties_func=self._extract_category_properties,
886
- get_additional_props_func=get_additional_props_with_format)
892
+ entity_type="Category",
893
+ extract_properties_func=self._extract_category_properties,
894
+ get_additional_props_func=get_additional_props_with_format)
887
895
 
888
896
  def generate_categories_md(self, elements: list | dict, search_string: str,
889
897
  output_format: str = 'MD') -> str | list:
@@ -1079,9 +1087,9 @@ class GlossaryBrowser(Client):
1079
1087
  #
1080
1088
 
1081
1089
  async def _async_find_glossaries(self, search_string: str, effective_time: str = None, starts_with: bool = False,
1082
- ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1083
- for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0, page_size: int = None,
1084
- output_format: str = 'JSON') -> list | str:
1090
+ ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1091
+ for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0,
1092
+ page_size: int = None, output_format: str = 'JSON') -> list | str:
1085
1093
  """Retrieve the list of glossary metadata elements that contain the search string. Async version.
1086
1094
  The search string is located in the request body and is interpreted as a plain string.
1087
1095
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1177,9 +1185,9 @@ class GlossaryBrowser(Client):
1177
1185
  return response.json().get("elementList", NO_GLOSSARIES_FOUND)
1178
1186
 
1179
1187
  def find_glossaries(self, search_string: str, effective_time: str = None, starts_with: bool = False,
1180
- ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1181
- for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0, page_size: int = None,
1182
- output_format: str = "JSON") -> list | str:
1188
+ ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1189
+ for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0,
1190
+ page_size: int = None, output_format: str = "JSON") -> list | str:
1183
1191
  """Retrieve the list of glossary metadata elements that contain the search string.
1184
1192
  The search string is located in the request body and is interpreted as a plain string.
1185
1193
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1241,12 +1249,12 @@ class GlossaryBrowser(Client):
1241
1249
  loop = asyncio.get_event_loop()
1242
1250
  response = loop.run_until_complete(
1243
1251
  self._async_find_glossaries(search_string, effective_time, starts_with, ends_with, ignore_case, for_lineage,
1244
- for_duplicate_processing, type_name, start_from, page_size, output_format))
1252
+ for_duplicate_processing, type_name, start_from, page_size, output_format))
1245
1253
 
1246
1254
  return response
1247
1255
 
1248
1256
  async def _async_get_glossary_by_guid(self, glossary_guid: str, effective_time: str = None,
1249
- output_format: str = "JSON") -> dict | str:
1257
+ output_format: str = "JSON") -> dict | str:
1250
1258
  """Retrieves information about a glossary
1251
1259
  Parameters
1252
1260
  ----------
@@ -1338,7 +1346,7 @@ class GlossaryBrowser(Client):
1338
1346
  return response
1339
1347
 
1340
1348
  async def _async_get_glossaries_by_name(self, glossary_name: str, effective_time: str = None, start_from: int = 0,
1341
- page_size: int = None, ) -> dict | str:
1349
+ page_size: int = None, ) -> dict | str:
1342
1350
  """Retrieve the list of glossary metadata elements with an exactly matching qualified or display name.
1343
1351
  There are no wildcards supported on this request.
1344
1352
 
@@ -1391,7 +1399,7 @@ class GlossaryBrowser(Client):
1391
1399
  return response.json().get("elementList", "No glossaries found")
1392
1400
 
1393
1401
  def get_glossaries_by_name(self, glossary_name: str, effective_time: str = None, start_from: int = 0,
1394
- page_size: int = None, ) -> dict | str:
1402
+ page_size: int = None, ) -> dict | str:
1395
1403
  """Retrieve the list of glossary metadata elements with an exactly matching qualified or display name.
1396
1404
  There are no wildcards supported on this request.
1397
1405
 
@@ -1435,7 +1443,7 @@ class GlossaryBrowser(Client):
1435
1443
  #
1436
1444
 
1437
1445
  async def _async_get_glossary_for_category(self, glossary_category_guid: str,
1438
- effective_time: str = None, ) -> dict | str:
1446
+ effective_time: str = None, ) -> dict | str:
1439
1447
  """Retrieve the glossary metadata element for the requested category. The optional request body allows you to
1440
1448
  specify that the glossary element should only be returned if it was effective at a particular time.
1441
1449
 
@@ -1514,8 +1522,9 @@ class GlossaryBrowser(Client):
1514
1522
  return response
1515
1523
 
1516
1524
  async def _async_get_glossary_subcategories(self, glossary_category_guid: str, effective_time: str = None,
1517
- start_from: int = 0, page_size: int = max_paging_size, for_lineage: bool = False,
1518
- for_duplicate_processing: bool = False, ) -> dict | str:
1525
+ start_from: int = 0, page_size: int = max_paging_size,
1526
+ for_lineage: bool = False,
1527
+ for_duplicate_processing: bool = False, ) -> dict | str:
1519
1528
  """Glossary categories can be organized in a hierarchy. Retrieve the subcategories for the glossary category
1520
1529
  metadata element with the supplied unique identifier. If the requested category does not have any subcategories,
1521
1530
  null is returned. The optional request body contain an effective time for the query.
@@ -1571,10 +1580,9 @@ class GlossaryBrowser(Client):
1571
1580
 
1572
1581
  return response.json().get("elementList", "No categories found")
1573
1582
 
1574
-
1575
1583
  def get_glossary_subcategories(self, glossary_category_guid: str, effective_time: str = None, start_from: int = 0,
1576
- page_size: int = max_paging_size, for_lineage: bool = False,
1577
- for_duplicate_processing: bool = False, ) -> dict | str:
1584
+ page_size: int = max_paging_size, for_lineage: bool = False,
1585
+ for_duplicate_processing: bool = False, ) -> dict | str:
1578
1586
  """Glossary categories can be organized in a hierarchy. Retrieve the subcategories for the glossary category
1579
1587
  metadata element with the supplied unique identifier. If the requested category does not have any subcategories,
1580
1588
  null is returned. The optional request body contain an effective time for the query.
@@ -1615,12 +1623,13 @@ class GlossaryBrowser(Client):
1615
1623
  loop = asyncio.get_event_loop()
1616
1624
  response = loop.run_until_complete(
1617
1625
  self._async_get_glossary_subcategories(glossary_category_guid, effective_time, start_from, page_size,
1618
- for_lineage, for_duplicate_processing))
1626
+ for_lineage, for_duplicate_processing))
1619
1627
  return response
1620
1628
 
1621
1629
  async def _async_find_glossary_categories(self, search_string: str, effective_time: str = None,
1622
- starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False, start_from: int = 0,
1623
- page_size: int = None, output_format: str = "JSON") -> list | str:
1630
+ starts_with: bool = False, ends_with: bool = False,
1631
+ ignore_case: bool = False, start_from: int = 0, page_size: int = None,
1632
+ output_format: str = "JSON") -> list | str:
1624
1633
  """Retrieve the list of glossary category metadata elements that contain the search string.
1625
1634
  The search string is located in the request body and is interpreted as a plain string.
1626
1635
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1704,8 +1713,8 @@ class GlossaryBrowser(Client):
1704
1713
  return response.json().get("elementList", NO_CATEGORIES_FOUND)
1705
1714
 
1706
1715
  def find_glossary_categories(self, search_string: str, effective_time: str = None, starts_with: bool = False,
1707
- ends_with: bool = False, ignore_case: bool = False, start_from: int = 0, page_size: int = None,
1708
- output_format: str = "JSON") -> list | str:
1716
+ ends_with: bool = False, ignore_case: bool = False, start_from: int = 0,
1717
+ page_size: int = None, output_format: str = "JSON") -> list | str:
1709
1718
  """Retrieve the list of glossary category metadata elements that contain the search string.
1710
1719
  The search string is located in the request body and is interpreted as a plain string.
1711
1720
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1759,12 +1768,12 @@ class GlossaryBrowser(Client):
1759
1768
  loop = asyncio.get_event_loop()
1760
1769
  response = loop.run_until_complete(
1761
1770
  self._async_find_glossary_categories(search_string, effective_time, starts_with, ends_with, ignore_case,
1762
- start_from, page_size, output_format))
1771
+ start_from, page_size, output_format))
1763
1772
 
1764
1773
  return response
1765
1774
 
1766
1775
  async def _async_get_categories_for_glossary(self, glossary_guid: str, start_from: int = 0,
1767
- page_size: int = None, ) -> list | str:
1776
+ page_size: int = None, ) -> list | str:
1768
1777
  """Return the list of categories associated with a glossary.
1769
1778
  Async version.
1770
1779
 
@@ -1807,7 +1816,7 @@ class GlossaryBrowser(Client):
1807
1816
  return response.json().get("elementList", "No Categories found")
1808
1817
 
1809
1818
  def get_categories_for_glossary(self, glossary_guid: str, start_from: int = 0,
1810
- page_size: int = None, ) -> list | str:
1819
+ page_size: int = None, ) -> list | str:
1811
1820
  """Return the list of categories associated with a glossary.
1812
1821
 
1813
1822
  Parameters
@@ -1844,7 +1853,7 @@ class GlossaryBrowser(Client):
1844
1853
  return response
1845
1854
 
1846
1855
  async def _async_get_categories_for_term(self, glossary_term_guid: str, start_from: int = 0,
1847
- page_size: int = None, ) -> list | str:
1856
+ page_size: int = None, ) -> list | str:
1848
1857
  """Return the list of categories associated with a glossary term.
1849
1858
  Async version.
1850
1859
 
@@ -1883,10 +1892,10 @@ class GlossaryBrowser(Client):
1883
1892
  f"{glossary_term_guid}/categories/retrieve?startFrom={start_from}&pageSize={page_size}")
1884
1893
 
1885
1894
  response = await self._async_make_request("POST", url)
1886
- return response.json().get("elementList", "No Categories found")
1895
+ return response.json().get("elementList", NO_CATEGORIES_FOUND)
1887
1896
 
1888
1897
  def get_categories_for_term(self, glossary_term_guid: str, start_from: int = 0,
1889
- page_size: int = None, ) -> list | str:
1898
+ page_size: int = None, ) -> list | str:
1890
1899
  """Return the list of categories associated with a glossary term.
1891
1900
 
1892
1901
  Parameters
@@ -1922,7 +1931,7 @@ class GlossaryBrowser(Client):
1922
1931
  return response
1923
1932
 
1924
1933
  async def _async_get_categories_by_name(self, name: str, glossary_guid: str = None, status: [str] = ["ACTIVE"],
1925
- start_from: int = 0, page_size: int = None, ) -> list | str:
1934
+ start_from: int = 0, page_size: int = None, ) -> list | str:
1926
1935
  """Retrieve the list of glossary category metadata elements that either have the requested qualified name or
1927
1936
  display name. The name to search for is located in the request body and is interpreted as a plain string.
1928
1937
  The request body also supports the specification of a glossaryGUID to restrict the search to within a single
@@ -1936,12 +1945,8 @@ class GlossaryBrowser(Client):
1936
1945
  category name to search for.
1937
1946
  glossary_guid: str, optional
1938
1947
  The identity of the glossary to search. If not specified, all glossaries will be searched.
1939
- status: [str], optional
1940
- A list of statuses to optionally restrict results. Default is Active
1941
-
1942
- If not provided, the server name associated with the instance is used.
1943
1948
  start_from: int, [default=0], optional
1944
- When multiple pages of results are available, the page number to start from.
1949
+ When multiple pages of results are available, the page number to start from.
1945
1950
  page_size: int, [default=None]
1946
1951
  The number of items to return in a single page. If not specified, the default will be taken from
1947
1952
  the class instance.
@@ -1980,7 +1985,7 @@ class GlossaryBrowser(Client):
1980
1985
  return response.json().get("elementList", NO_CATEGORIES_FOUND)
1981
1986
 
1982
1987
  def get_categories_by_name(self, name: str, glossary_guid: str = None, status: [str] = ["ACTIVE"],
1983
- start_from: int = 0, page_size: int = None, ) -> list | str:
1988
+ start_from: int = 0, page_size: int = None) -> list | str:
1984
1989
  """Retrieve the list of glossary category metadata elements that either have the requested qualified name or
1985
1990
  display name. The name to search for is located in the request body and is interpreted as a plain string.
1986
1991
  The request body also supports the specification of a glossaryGUID to restrict the search to within a
@@ -1992,10 +1997,6 @@ class GlossaryBrowser(Client):
1992
1997
  category name to search for.
1993
1998
  glossary_guid: str, optional
1994
1999
  The identity of the glossary to search. If not specified, all glossaries will be searched.
1995
- status: [str], optional
1996
- A list of statuses to optionally restrict results. Default is Active
1997
-
1998
- If not provided, the server name associated with the instance is used.
1999
2000
  start_from: int, [default=0], optional
2000
2001
  When multiple pages of results are available, the page number to start from.
2001
2002
  page_size: int, [default=None]
@@ -2287,18 +2288,13 @@ class GlossaryBrowser(Client):
2287
2288
  parent_guid = parent['elementHeader']['guid']
2288
2289
  parent_name = parent['glossaryCategoryProperties'].get('displayName', '---')
2289
2290
  parent_info = {
2290
- 'guid': parent_guid,
2291
- 'name': parent_name
2292
- }
2291
+ 'guid': parent_guid, 'name': parent_name
2292
+ }
2293
2293
 
2294
2294
  return {
2295
- 'guid': category_guid,
2296
- 'name': display_name,
2297
- 'qualifiedName': qualified_name,
2298
- 'description': description,
2299
- 'parent': parent_info,
2300
- 'children': children
2301
- }
2295
+ 'guid': category_guid, 'name': display_name, 'qualifiedName': qualified_name,
2296
+ 'description': description, 'parent': parent_info, 'children': children
2297
+ }
2302
2298
 
2303
2299
  # Build tree for each root category
2304
2300
  for root_guid in root_guids:
@@ -2309,9 +2305,8 @@ class GlossaryBrowser(Client):
2309
2305
  # Format the output according to the specified output_format
2310
2306
  if output_format == "DICT":
2311
2307
  return {
2312
- 'glossary_guid': glossary_guid,
2313
- 'categories': category_tree
2314
- }
2308
+ 'glossary_guid': glossary_guid, 'categories': category_tree
2309
+ }
2315
2310
  elif output_format == "LIST":
2316
2311
  # Generate markdown table
2317
2312
  md_table = "| Category | Path | Description | Parent Category | Child Categories |\n"
@@ -2333,7 +2328,9 @@ class GlossaryBrowser(Client):
2333
2328
  child_names.append(child['name'])
2334
2329
  child_categories = ", ".join(child_names) if child_names else "None"
2335
2330
 
2336
- md_table += f"| {category['name']} | {category_path} | {self._format_for_markdown_table(category['description'])} | {parent_name} | {child_categories} |\n"
2331
+ md_table += (f"| {category['name']} | {category_path} | "
2332
+ f"{self._format_for_markdown_table(category['description'])} | "
2333
+ f"{parent_name} | {child_categories} |\n")
2337
2334
  if category['children']:
2338
2335
  add_categories_to_table(category['children'], category_path)
2339
2336
 
@@ -2365,14 +2362,12 @@ class GlossaryBrowser(Client):
2365
2362
  else:
2366
2363
  return f"Unsupported output format: {output_format}. Use 'DICT', 'LIST', or 'MD'."
2367
2364
 
2368
-
2369
-
2370
2365
  #
2371
2366
  # Terms
2372
2367
  #
2373
2368
 
2374
2369
  async def _async_get_terms_for_category(self, glossary_category_guid: str, effective_time: str = None,
2375
- start_from: int = 0, page_size: int = None, ) -> list | str:
2370
+ start_from: int = 0, page_size: int = None, ) -> list | str:
2376
2371
  """Retrieve ALL the glossary terms in a category.
2377
2372
  The request body also supports the specification of an effective time for the query.
2378
2373
 
@@ -2423,7 +2418,7 @@ class GlossaryBrowser(Client):
2423
2418
  return response.json().get("elementList", "No terms found")
2424
2419
 
2425
2420
  def get_terms_for_category(self, glossary_category_guid: str, effective_time: str = None, start_from: int = 0,
2426
- page_size: int = None, ) -> list | str:
2421
+ page_size: int = None, ) -> list | str:
2427
2422
  """Retrieve ALL the glossary terms in a category.
2428
2423
  The request body also supports the specification of an effective time for the query.
2429
2424
 
@@ -2464,7 +2459,7 @@ class GlossaryBrowser(Client):
2464
2459
  return response
2465
2460
 
2466
2461
  async def _async_get_terms_for_glossary(self, glossary_guid: str, effective_time: str = None, start_from: int = 0,
2467
- page_size: int = None, ) -> list | str:
2462
+ page_size: int = None, ) -> list | str:
2468
2463
  """Retrieve the list of glossary terms associated with a glossary.
2469
2464
  The request body also supports the specification of an effective time for the query.
2470
2465
  Parameters
@@ -2513,7 +2508,7 @@ class GlossaryBrowser(Client):
2513
2508
  return response.json().get("elementList", "No terms found")
2514
2509
 
2515
2510
  def get_terms_for_glossary(self, glossary_guid: str, effective_time: str = None, start_from: int = 0,
2516
- page_size: int = None, ) -> list | str:
2511
+ page_size: int = None, ) -> list | str:
2517
2512
  """Retrieve the list of glossary terms associated with a glossary.
2518
2513
  The request body also supports the specification of an effective time for the query.
2519
2514
  Parameters
@@ -2551,7 +2546,7 @@ class GlossaryBrowser(Client):
2551
2546
  return response
2552
2547
 
2553
2548
  async def _async_get_related_terms(self, term_guid: str, effective_time: str = None, start_from: int = 0,
2554
- page_size: int = None, output_format:str = "JSON") -> list | str:
2549
+ page_size: int = None, output_format: str = "JSON") -> list | str:
2555
2550
  """This call retrieves details of the glossary terms linked to this glossary term.
2556
2551
  Notice the original org 1 glossary term is linked via the "SourcedFrom" relationship.
2557
2552
  Parameters
@@ -2606,12 +2601,11 @@ class GlossaryBrowser(Client):
2606
2601
  elif output_format == 'DICT':
2607
2602
  return None
2608
2603
  if output_format != "JSON": # return a simplified markdown representation
2609
- return self.generate_terms_md(term_elements, term_guid, output_format)
2604
+ return self.generate_related_terms_md(term_elements, term_guid, output_format)
2610
2605
  return response.json().get("elementList", NO_TERMS_FOUND)
2611
2606
 
2612
-
2613
- def get_related_terms(self, term_guid: str, effective_time: str = None, start_from: int = 0,
2614
- page_size: int = None, output_format = "JSON") -> list | str:
2607
+ def get_related_terms(self, term_guid: str, effective_time: str = None, start_from: int = 0, page_size: int = None,
2608
+ output_format="JSON") -> list | str:
2615
2609
  """This call retrieves details of the glossary terms linked to this glossary term.
2616
2610
  Notice the original org 1 glossary term is linked via the "SourcedFrom" relationship..
2617
2611
  Parameters
@@ -2644,36 +2638,205 @@ class GlossaryBrowser(Client):
2644
2638
  """
2645
2639
  loop = asyncio.get_event_loop()
2646
2640
  response = loop.run_until_complete(
2647
- self._async_get_related_terms(term_guid, effective_time, start_from,
2648
- page_size, output_format))
2641
+ self._async_get_related_terms(term_guid, effective_time, start_from, page_size, output_format))
2649
2642
 
2650
2643
  return response
2651
2644
 
2652
- def get_term_details(self, term_name:str, effective_time: str = None) -> dict | str:
2653
- """Retrieve the details of a glossary term. Including relationships and feedback
2645
+ def generate_related_terms_md(self, term_elements: list, term_guid: str, output_format: str = 'MD') -> str | list:
2646
+ """
2647
+ Generate a simplified representation of related terms.
2654
2648
 
2655
- output_format: str, default = 'JSON'
2649
+ Args:
2650
+ term_elements (list): List of term elements with relationship information
2651
+ term_guid (str): GUID of the term for which to generate related terms
2652
+ output_format (str): Output format (MD, LIST, DICT, etc.)
2653
+
2654
+ Returns:
2655
+ str | list: Markdown string or list of dictionaries depending on output_format
2656
+ """
2657
+ # Get the first term's display name and qualified name
2658
+ term_name = "Term"
2659
+ try:
2660
+ term_info = self.get_term_by_guid(term_guid, output_format="DICT")
2661
+ # Handle case where term_info is a list of dictionaries
2662
+ if isinstance(term_info, list) and len(term_info) > 0:
2663
+ term_info = term_info[0] # Get the first term
2664
+ if isinstance(term_info, dict) and 'display_name' in term_info:
2665
+ term_name = term_info['display_name']
2666
+ except:
2667
+ # If we can't get the term info, just use the default name
2668
+ pass
2669
+
2670
+ # Create a list to store the simplified related terms
2671
+ related_terms = []
2672
+
2673
+ # Process each term element
2674
+ for element in term_elements:
2675
+ # Extract relationship type from the relationship header
2676
+ relationship_type = element['relatedElement']['relationshipHeader']['type']['typeName']
2677
+
2678
+ # Extract related term information
2679
+ related_term = {
2680
+ 'first_term_display_name': term_name, 'first_term_qualified_name': term_info.get('qualified_name', ''),
2681
+ 'related_term_display_name': element['glossaryTermProperties'].get('displayName', ''),
2682
+ 'related_term_qualified_name': element['glossaryTermProperties'].get('qualifiedName', ''),
2683
+ 'relationship_type': relationship_type
2684
+ }
2685
+
2686
+ related_terms.append(related_term)
2687
+
2688
+ # Return based on output format
2689
+ if output_format == 'DICT':
2690
+ return related_terms
2691
+
2692
+ # For MD, LIST, FORM, REPORT formats, create a markdown representation
2693
+ md_output = f"# Related Terms for {term_name}\n\n"
2694
+
2695
+ if output_format == 'LIST':
2696
+ # Create a table
2697
+ md_output += ("| First Term | First Term Qualified Name | Related Term | Related Term Qualified Name | "
2698
+ "Relationship Type |\n")
2699
+ md_output += \
2700
+ "|------------|---------------------------|--------------|------------------------------|-------------------|\n"
2701
+
2702
+ for term in related_terms:
2703
+ md_output += f"| {term['first_term_display_name']} | {term['first_term_qualified_name']} | "
2704
+ md_output += f"{term['related_term_display_name']} | {term['related_term_qualified_name']} | "
2705
+ md_output += f"{term['relationship_type']} |\n"
2706
+ else:
2707
+ # For other formats, create a more detailed representation
2708
+ for term in related_terms:
2709
+ md_output += f"## {term['relationship_type']} Relationship\n\n"
2710
+ md_output += (f"**First Term:** {term['first_term_display_name']} ("
2711
+ f"{term['first_term_qualified_name']})\n\n")
2712
+ md_output += f"**Related Term:** {term[('related_term_dis'
2713
+ 'play_name')]} ({term['related_term_qualified_name']})\n\n"
2714
+ md_output += "---\n\n"
2715
+
2716
+ return md_output
2717
+
2718
+ def get_term_details(self, term_name: str, effective_time: str = None, output_format: str = 'DICT') -> dict | str:
2719
+ """Retrieve detailed information about a term, combining basic term details and related terms.
2720
+
2721
+ This method combines the term details retrieved from get_term_by_guid and the related terms
2722
+ information from generate_related_terms_md.
2723
+
2724
+ Parameters
2725
+ ----------
2726
+ term_name : str
2727
+ Either the display name or the qualified name of the term to retrieve.
2728
+ effective_time : str, optional
2729
+ Time at which the term is active. If not specified, the current time is used.
2730
+ output_format : str, default = 'DICT'
2656
2731
  Type of output to produce:
2657
- JSON - output standard json
2658
- MD - output standard markdown with no preamble
2659
- DICT = output a simplified DICT structure
2732
+ DICT - output a dictionary with combined term details and related terms
2733
+ REPORT - output a markdown report with combined term details and related terms
2734
+
2735
+ Returns
2736
+ -------
2737
+ dict | str
2738
+ A dictionary or markdown string containing the combined term details and related terms.
2739
+
2740
+ Raises
2741
+ ------
2742
+ InvalidParameterException
2743
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2744
+ PropertyServerException
2745
+ Raised by the server when an issue arises in processing a valid request.
2746
+ NotAuthorizedException
2747
+ The principle specified by the user_id does not have authorization for the requested action.
2660
2748
  """
2749
+ # Check if the output format is supported
2750
+ if output_format not in ["DICT", "REPORT"]:
2751
+ return f"Unsupported output format: {output_format}. Supported formats are DICT and REPORT."
2661
2752
 
2753
+ # Search for the term using the qualified name
2754
+ terms = self.get_terms_by_name(term_name, effective_time=effective_time, output_format="DICT")
2662
2755
 
2663
- # Now lets get the term details as a dict
2664
- core = self.get_terms_by_name(term_name, effective_time, output_format="DICT")
2665
- if not core:
2666
- return NO_TERMS_FOUND
2756
+ # Check if we found any terms
2757
+ if not terms or (isinstance(terms, str) and terms == NO_TERMS_FOUND):
2758
+ return f"No term found with name: {term_name}"
2667
2759
 
2668
- related = self.get_related_terms(core[0]['guid'], effective_time)
2669
- if not related:
2670
- return "NO RELATED TERMS FOUND"
2760
+ # Make sure we only have one term
2761
+ if isinstance(terms, list) and len(terms) > 1:
2762
+ return f"Multiple terms found with name: {term_name} - please specify the qualified name."
2671
2763
 
2672
- related_term_guid = related[0]["relatedElement"]["relatedElement"]["guid"]
2673
- related_term_qn = related[0]["relatedElement"]["relatedElement"]["uniquedName"]
2764
+ term_details = terms[0]
2674
2765
 
2766
+ # Get related terms
2767
+ try:
2768
+ related_terms_response = self.get_related_terms(term_details.get('guid', ''), output_format="DICT")
2769
+ except (InvalidParameterException, PropertyServerException, UserNotAuthorizedException):
2770
+ # If we can't get related terms, set to empty list
2771
+ related_terms_response = []
2675
2772
 
2773
+ # If no related terms were found, set to empty list
2774
+ if isinstance(related_terms_response, str) and related_terms_response == NO_TERMS_FOUND:
2775
+ related_terms = []
2776
+ elif related_terms_response is None:
2777
+ related_terms = []
2778
+ else:
2779
+ related_terms = related_terms_response
2676
2780
 
2781
+ # Combine the data
2782
+ if output_format == "DICT":
2783
+ # Create a combined dictionary
2784
+ combined_data = {
2785
+ "term_details": term_details, "related_terms": related_terms
2786
+ }
2787
+ return combined_data
2788
+ elif output_format == "REPORT":
2789
+ # Create a markdown report
2790
+ md_output = f"# Term Details Report for `{term_name}` \n\n"
2791
+
2792
+ # Add term details
2793
+ md_output += "## Basic Term Information\n\n"
2794
+ md_output += f"**Display Name:** {term_details.get('display_name', '')}\n\n"
2795
+ md_output += f"**Qualified Name:** {term_details.get('qualified_name', '')}\n\n"
2796
+ md_output += f"**GUID:** {term_details.get('guid', '')}\n\n"
2797
+
2798
+ if 'summary' in term_details and term_details['summary']:
2799
+ md_output += f"**Summary:** {term_details.get('summary', '')}\n\n"
2800
+
2801
+ if 'description' in term_details and term_details['description']:
2802
+ md_output += f"**Description:** {term_details.get('description', '')}\n\n"
2803
+
2804
+ if 'examples' in term_details and term_details['examples']:
2805
+ md_output += f"**Examples:** {term_details.get('examples', '')}\n\n"
2806
+
2807
+ if 'usage' in term_details and term_details['usage']:
2808
+ md_output += f"**Usage:** {term_details.get('usage', '')}\n\n"
2809
+
2810
+ if 'aliases' in term_details and term_details['aliases']:
2811
+ md_output += f"**Aliases:** {term_details.get('aliases', '')}\n\n"
2812
+
2813
+ if 'status' in term_details and term_details['status']:
2814
+ md_output += f"**Status:** {term_details.get('status', '')}\n\n"
2815
+
2816
+ if 'in_glossary' in term_details and term_details['in_glossary']:
2817
+ md_output += f"**Glossary:** {term_details.get('in_glossary', '')}\n\n"
2818
+
2819
+ if 'categories' in term_details and term_details['categories']:
2820
+ md_output += f"**Categories:** {', '.join(term_details.get('categories', []))}\n\n"
2821
+
2822
+ # Add related terms
2823
+ md_output += "## Related Terms\n\n"
2824
+
2825
+ if not related_terms:
2826
+ md_output += "No related terms found.\n\n"
2827
+ else:
2828
+ # Create a table for related terms
2829
+ md_output += "| Related Term | Qualified Name | Relationship Type |\n"
2830
+ md_output += "|--------------|---------------|-------------------|\n"
2831
+
2832
+ for term in related_terms:
2833
+ md_output += f"| {term.get('related_term_display_name', '')} | "
2834
+ md_output += f"{term.get('related_term_qualified_name', '')} | "
2835
+ md_output += f"{term.get('relationship_type', '')} |\n"
2836
+
2837
+ return md_output
2838
+ else:
2839
+ return f"Unsupported output format: {output_format}. Supported formats are DICT and REPORT."
2677
2840
 
2678
2841
  async def _async_get_glossary_for_term(self, term_guid: str, effective_time: str = None) -> dict | str:
2679
2842
  """Retrieve the glossary metadata element for the requested term. The optional request body allows you to
@@ -2752,8 +2915,9 @@ class GlossaryBrowser(Client):
2752
2915
  return response
2753
2916
 
2754
2917
  async def _async_get_terms_by_name(self, term: str, glossary_guid: str = None, status_filter: list = [],
2755
- effective_time: str = None, for_lineage: bool = False, for_duplicate_processing: bool = False,
2756
- start_from: int = 0, page_size: int = None, output_format = "JSON") -> list:
2918
+ effective_time: str = None, for_lineage: bool = False,
2919
+ for_duplicate_processing: bool = False, start_from: int = 0,
2920
+ page_size: int = None, output_format="JSON") -> list:
2757
2921
  """Retrieve glossary terms by display name or qualified name. Async Version.
2758
2922
 
2759
2923
  Parameters
@@ -2831,10 +2995,9 @@ class GlossaryBrowser(Client):
2831
2995
  return self.generate_terms_md(term_elements, term, output_format)
2832
2996
  return response.json().get("elementList", NO_TERMS_FOUND)
2833
2997
 
2834
-
2835
2998
  def get_terms_by_name(self, term: str, glossary_guid: str = None, status_filter: list = [],
2836
- effective_time: str = None, for_lineage: bool = False, for_duplicate_processing: bool = False,
2837
- start_from: int = 0, page_size: int = None, output_format = "JSON") -> list:
2999
+ effective_time: str = None, for_lineage: bool = False, for_duplicate_processing: bool = False,
3000
+ start_from: int = 0, page_size: int = None, output_format="JSON") -> list:
2838
3001
  """Retrieve glossary terms by display name or qualified name.
2839
3002
 
2840
3003
  Parameters
@@ -2883,7 +3046,7 @@ class GlossaryBrowser(Client):
2883
3046
  loop = asyncio.get_event_loop()
2884
3047
  response = loop.run_until_complete(
2885
3048
  self._async_get_terms_by_name(term, glossary_guid, status_filter, effective_time, for_lineage,
2886
- for_duplicate_processing, start_from, page_size, output_format))
3049
+ for_duplicate_processing, start_from, page_size, output_format))
2887
3050
  return response
2888
3051
 
2889
3052
  async def _async_get_term_by_guid(self, term_guid: str, output_format: str = 'JSON') -> dict | str:
@@ -2960,10 +3123,11 @@ class GlossaryBrowser(Client):
2960
3123
  return response
2961
3124
 
2962
3125
  async def _async_get_term_versions(self, term_guid: str, effective_time: str = None, from_time: str = None,
2963
- to_time: str = None, oldest_first: bool = False, for_lineage: bool = False,
2964
- for_duplicate_processing: bool = False, start_from: int = 0, page_size=max_paging_size,
3126
+ to_time: str = None, oldest_first: bool = False, for_lineage: bool = False,
3127
+ for_duplicate_processing: bool = False, start_from: int = 0,
3128
+ page_size=max_paging_size,
2965
3129
 
2966
- ) -> list | str:
3130
+ ) -> list | str:
2967
3131
  """Retrieve the versions of a glossary term. Async version.
2968
3132
  Parameters
2969
3133
  ----------
@@ -3017,8 +3181,8 @@ class GlossaryBrowser(Client):
3017
3181
  return response.json().get("elementList", "No term found")
3018
3182
 
3019
3183
  def get_term_versions(self, term_guid: str, effective_time: str = None, from_time: str = None, to_time: str = None,
3020
- oldest_first: bool = False, for_lineage: bool = False, for_duplicate_processing: bool = False,
3021
- start_from: int = 0, page_size=max_paging_size, ) -> dict | str:
3184
+ oldest_first: bool = False, for_lineage: bool = False, for_duplicate_processing: bool = False,
3185
+ start_from: int = 0, page_size=max_paging_size, ) -> dict | str:
3022
3186
  """Retrieve the versions of a glossary term.
3023
3187
  Parameters
3024
3188
  ----------
@@ -3123,7 +3287,7 @@ class GlossaryBrowser(Client):
3123
3287
  return response
3124
3288
 
3125
3289
  async def _async_get_term_revision_history(self, term_revision_log_guid: str, start_from: int = 0,
3126
- page_size=None, ) -> dict | str:
3290
+ page_size=None, ) -> dict | str:
3127
3291
  """Retrieve the revision history for a glossary term. Async version.
3128
3292
 
3129
3293
  Parameters
@@ -3168,7 +3332,7 @@ class GlossaryBrowser(Client):
3168
3332
  return response.json().get("elementList", "No logs found")
3169
3333
 
3170
3334
  def get_term_revision_history(self, term_revision_log_guid: str, start_from: int = 0,
3171
- page_size=None, ) -> dict | str:
3335
+ page_size=None, ) -> dict | str:
3172
3336
  """Retrieve the revision history for a glossary term.
3173
3337
 
3174
3338
  Parameters
@@ -3230,7 +3394,6 @@ class GlossaryBrowser(Client):
3230
3394
  If output_format is "LIST", returns a markdown table of the revision history.
3231
3395
  If no revision logs are found, returns a string message "No revision logs found".
3232
3396
  """
3233
- import re
3234
3397
  validate_guid(term_guid)
3235
3398
 
3236
3399
  # Get revision logs for the term
@@ -3258,15 +3421,15 @@ class GlossaryBrowser(Client):
3258
3421
  update_time = title[keyword_index + 2:].strip()
3259
3422
 
3260
3423
  entry_data = {
3261
- 'qualifiedName': qualified_name,
3262
- 'title': title,
3263
- 'text': entry.get('properties', {}).get('text', '---'),
3264
- 'updateTime': update_time # Use extracted date/time or fall back to title
3265
- }
3424
+ 'qualifiedName': qualified_name, 'title': title,
3425
+ 'text': entry.get('properties', {}).get('text', '---'), 'updateTime': update_time
3426
+ # Use extracted date/time or fall back to title
3427
+ }
3266
3428
  all_entries.append(entry_data)
3267
3429
 
3268
3430
  # Sort entries by update time
3269
- sorted_entries = sorted(all_entries, key=lambda x: x['updateTime'] if x['updateTime'] != '---' else '', reverse=True)
3431
+ sorted_entries = sorted(all_entries, key=lambda x: x['updateTime'] if x['updateTime'] != '---' else '',
3432
+ reverse=True)
3270
3433
 
3271
3434
  # Return in the specified format
3272
3435
  if output_format == "DICT":
@@ -3310,7 +3473,6 @@ class GlossaryBrowser(Client):
3310
3473
  # Default to DICT format
3311
3474
  return sorted_entries
3312
3475
 
3313
-
3314
3476
  def list_full_term_history(self, term_guid: str, output_type: str = "DICT") -> list | str:
3315
3477
  """
3316
3478
  Retrieves and formats the entire version history of a specific term in the repository.
@@ -3385,9 +3547,10 @@ class GlossaryBrowser(Client):
3385
3547
  return None
3386
3548
 
3387
3549
  async def _async_find_glossary_terms(self, search_string: str, glossary_guid: str = None, status_filter: list = [],
3388
- effective_time: str = None, starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False,
3389
- for_lineage: bool = False, for_duplicate_processing: bool = False, start_from: int = 0,
3390
- page_size: int = None, output_format: str = "JSON", ) -> list | str:
3550
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3551
+ ignore_case: bool = False, for_lineage: bool = False,
3552
+ for_duplicate_processing: bool = False, start_from: int = 0,
3553
+ page_size: int = None, output_format: str = "JSON", ) -> list | str:
3391
3554
  """Retrieve the list of glossary term metadata elements that contain the search string.
3392
3555
 
3393
3556
  Parameters
@@ -3486,9 +3649,10 @@ class GlossaryBrowser(Client):
3486
3649
  return response.json().get("elementList", NO_TERMS_FOUND)
3487
3650
 
3488
3651
  def find_glossary_terms(self, search_string: str, glossary_guid: str = None, status_filter: list = [],
3489
- effective_time: str = None, starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False,
3490
- for_lineage: bool = False, for_duplicate_processing: bool = False, start_from: int = 0,
3491
- page_size: int = None, output_format: str = "JSON", ) -> list | str:
3652
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3653
+ ignore_case: bool = False, for_lineage: bool = False,
3654
+ for_duplicate_processing: bool = False, start_from: int = 0, page_size: int = None,
3655
+ output_format: str = "JSON", ) -> list | str:
3492
3656
  """Retrieve the list of glossary term metadata elements that contain the search string.
3493
3657
 
3494
3658
  Parameters
@@ -3553,7 +3717,8 @@ class GlossaryBrowser(Client):
3553
3717
  loop = asyncio.get_event_loop()
3554
3718
  response = loop.run_until_complete(
3555
3719
  self._async_find_glossary_terms(search_string, glossary_guid, status_filter, effective_time, starts_with,
3556
- ends_with, ignore_case, for_lineage, for_duplicate_processing, start_from, page_size, output_format))
3720
+ ends_with, ignore_case, for_lineage, for_duplicate_processing, start_from,
3721
+ page_size, output_format))
3557
3722
 
3558
3723
  return response
3559
3724
 
@@ -3561,7 +3726,7 @@ class GlossaryBrowser(Client):
3561
3726
  # Feedback
3562
3727
  #
3563
3728
  async def _async_get_comment(self, commemt_guid: str, effective_time: str, for_lineage: bool = False,
3564
- for_duplicate_processing: bool = False, ) -> dict | list:
3729
+ for_duplicate_processing: bool = False, ) -> dict | list:
3565
3730
  """Retrieve the comment specified by the comment GUID"""
3566
3731
 
3567
3732
  validate_guid(commemt_guid)
@@ -3584,7 +3749,7 @@ class GlossaryBrowser(Client):
3584
3749
  return response.json()
3585
3750
 
3586
3751
  async def _async_add_comment_reply(self, comment_guid: str, is_public: bool, comment_type: str, comment_text: str,
3587
- for_lineage: bool = False, for_duplicate_processing: bool = False, ) -> str:
3752
+ for_lineage: bool = False, for_duplicate_processing: bool = False, ) -> str:
3588
3753
  """Reply to a comment"""
3589
3754
 
3590
3755
  validate_guid(comment_guid)
@@ -3609,7 +3774,8 @@ class GlossaryBrowser(Client):
3609
3774
  return response
3610
3775
 
3611
3776
  async def _async_update_comment(self, comment_guid: str, is_public: bool, comment_type: str, comment_text: str,
3612
- is_merge_update: bool = False, for_lineage: bool = False, for_duplicate_processing: bool = False, ) -> str:
3777
+ is_merge_update: bool = False, for_lineage: bool = False,
3778
+ for_duplicate_processing: bool = False, ) -> str:
3613
3779
  """Update the specified comment"""
3614
3780
 
3615
3781
  validate_guid(comment_guid)
@@ -3634,9 +3800,9 @@ class GlossaryBrowser(Client):
3634
3800
  return response
3635
3801
 
3636
3802
  async def _async_find_comment(self, search_string: str, glossary_guid: str = None, status_filter: list = [],
3637
- effective_time: str = None, starts_with: bool = False, ends_with: bool = False, ignore_case: bool = False,
3638
- for_lineage: bool = False, for_duplicate_processing: bool = False, start_from: int = 0,
3639
- page_size: int = None, ):
3803
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3804
+ ignore_case: bool = False, for_lineage: bool = False,
3805
+ for_duplicate_processing: bool = False, start_from: int = 0, page_size: int = None, ):
3640
3806
  """Find comments by search string"""
3641
3807
 
3642
3808
  if page_size is None:
@@ -25,7 +25,7 @@ from pyegeria.project_manager_omvs import ProjectManager
25
25
  EGERIA_WIDTH = int(os.environ.get("EGERIA_WIDTH", "170"))
26
26
  console = Console(width=EGERIA_WIDTH)
27
27
 
28
- command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms",
28
+ command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term", "Update Term", "List Terms", "List Term Details",
29
29
  "List Glossary Terms", "List Term History", "List Term Revision History", "List Term Update History",
30
30
  "List Glossary Structure", "List Glossaries", "List Categories", "List Glossary Categories",
31
31
  "Create Personal Project", "Update Personal Project", "Create Category", "Update Category",
@@ -360,8 +360,7 @@ def update_a_command(txt: str, command: str, obj_type: str, q_name: str, u_guid:
360
360
  verb = command.split(' ')[0].strip()
361
361
  action = "Update" if (verb == "Create" and u_guid is not None) else "Create"
362
362
  txt = txt.replace(f"{command}", f'{action} {obj_type}\n') # update the command
363
- txt = txt.replace('<GUID>', f'GUID\n{u_guid}') # update with GUID
364
- txt = txt.replace('<Qualified Name>', f"Qualified Name\n{q_name}")
363
+
365
364
  if "Qualified Name" not in txt:
366
365
  txt += f"\n## Qualified Name\n{q_name}\n"
367
366
  if "GUID" not in txt:
@@ -978,11 +977,13 @@ def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directi
978
977
  if valid:
979
978
  print(Markdown(glossary_display))
980
979
  else:
981
- msg = f"Validation failed for Glossary `{glossary_name}`\n"
982
- print_msg(ERROR, msg, debug_level)
983
- print(Markdown(glossary_display))
984
- return None
985
-
980
+ if glossary_exists and object_action == "Create":
981
+ msg = f"Create failed because glossary `{glossary_name}` exists - changing `Create` to `Update` in processed output \n"
982
+ print_msg(ERROR, msg, debug_level)
983
+ print(Markdown(glossary_display))
984
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
985
+ else:
986
+ return None
986
987
  if object_action == "Update":
987
988
  if not glossary_exists:
988
989
  print(f"\n{ERROR}Glossary `{glossary_name}` does not exist! Updating result document with Create "
@@ -1123,10 +1124,13 @@ def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directi
1123
1124
  if valid:
1124
1125
  print(Markdown(category_display))
1125
1126
  else:
1126
- msg = f"* --> Validation failed for {object_type} `{category_name}`\n"
1127
- print_msg(ERROR, msg, debug_level)
1128
- print(Markdown(category_display))
1129
- return None
1127
+ if category_exists and object_action == "Create":
1128
+ msg = f"Create failed because category `{category_name}` exists - changing `Create` to `Update` in processed output \n"
1129
+ print_msg(ERROR, msg, debug_level)
1130
+ print(Markdown(category_display))
1131
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1132
+ else:
1133
+ return None
1130
1134
 
1131
1135
  if object_action == "Update":
1132
1136
  if not category_exists:
@@ -1173,7 +1177,7 @@ def process_category_upsert_command(egeria_client: EgeriaTech, txt: str, directi
1173
1177
  'guid': category_guid, 'display_name': category_name
1174
1178
  })
1175
1179
  print_msg(ALWAYS, f"Created Category `{category_name}` with GUID {category_guid}", debug_level)
1176
- if parent_valid & parent_exists:
1180
+ if parent_valid and parent_guid:
1177
1181
  egeria_client.set_parent_category(parent_guid, category_guid)
1178
1182
  print_msg(ALWAYS, f"Set parent category for `{category_name}` to `{parent_category_name}`",
1179
1183
  debug_level)
@@ -1297,7 +1301,7 @@ def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive:
1297
1301
  version = process_simple_attribute(txt, ['Version', "Version Identifier", "Published Version"], INFO)
1298
1302
  q_name = process_simple_attribute(txt, ['Qualified Name'], INFO)
1299
1303
 
1300
- aliases = process_simple_attribute(txt, ['Aliases'], INFO)
1304
+ aliases = process_simple_attribute(txt, ['Aliases','Alias'], INFO)
1301
1305
  if aliases:
1302
1306
  alias_list = list(filter(None, re.split(r'[,\s]+', aliases.strip())))
1303
1307
  else:
@@ -1382,7 +1386,14 @@ def process_term_upsert_command(egeria_client: EgeriaTech, txt: str, directive:
1382
1386
  elif directive == "process":
1383
1387
  try:
1384
1388
  if not valid: # First validate the term before we process it
1385
- return None
1389
+ if term_exists and object_action == "Create":
1390
+ msg = f"Create failed because term `{term_name}` exists - changing `Create` to `Update` in processed output \n"
1391
+ print_msg(ERROR, msg, debug_level)
1392
+ print(Markdown(term_display))
1393
+ return update_a_command(txt, command, object_type, known_q_name, known_guid)
1394
+ else:
1395
+ return None
1396
+
1386
1397
  print(Markdown(term_display))
1387
1398
  if object_action == "Update" and directive == "process":
1388
1399
  if not term_exists:
@@ -1471,16 +1482,16 @@ def process_create_term_term_relationship_command(egeria_client: EgeriaTech, txt
1471
1482
  term2_guid = None
1472
1483
 
1473
1484
 
1474
- term_relationship = process_simple_attribute(txt, ["Term Relationship"], "ERROR")
1485
+ term_relationship = process_simple_attribute(txt, ["Term Relationship", "Relationship Type"], "ERROR")
1475
1486
  if term_relationship not in TERM_RELATIONSHPS:
1476
1487
  valid = False
1477
1488
 
1478
1489
  print(Markdown(f"{pre_command} `{command}` for term relationship: `{term_relationship}` with directive: `{directive}` "))
1479
1490
 
1480
- term1_q_name, term1_guid, term1_valid, term1_exists = process_element_identifiers(egeria_client, object_type, ["Term 1 Name"], txt,
1491
+ term1_q_name, term1_guid, term1_valid, term1_exists = process_element_identifiers(egeria_client, object_type, ["Term 1 Name", "Term 1"], txt,
1481
1492
  "Exists Required", None )
1482
1493
 
1483
- term2_q_name, term2_guid, term2_valid, term2_exists = process_element_identifiers(egeria_client, object_type, ["Term 2 Name"], txt,
1494
+ term2_q_name, term2_guid, term2_valid, term2_exists = process_element_identifiers(egeria_client, object_type, ["Term 2 Name", "Term 2"], txt,
1484
1495
  "Exists Required", None )
1485
1496
 
1486
1497
  request_display = (f"\n\t* Term 1 Qualified Name: {term1_q_name}\n\t* Term 2 Qualified Name {term2_q_name}\n\t"
@@ -1515,7 +1526,6 @@ def process_create_term_term_relationship_command(egeria_client: EgeriaTech, txt
1515
1526
  return None
1516
1527
 
1517
1528
 
1518
-
1519
1529
  def process_per_proj_upsert_command(egeria_client: ProjectManager, txt: str, directive: str = "display") -> str | None:
1520
1530
  """
1521
1531
  Processes a personal project create or update command by extracting key attributes such as
@@ -1678,7 +1688,7 @@ def process_term_list_command(egeria_client: EgeriaTech, txt: str, directive: st
1678
1688
  search_string = '*'
1679
1689
  print(Markdown(f"{pre_command} `{command}` with search string:`{search_string}` with directive: `{directive}`"))
1680
1690
 
1681
- glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary'])
1691
+ glossary = process_simple_attribute(txt, ['Glossary', 'In Glossary', "Glossary Name"])
1682
1692
  if glossary is not None:
1683
1693
  _, glossary_guid, _, glossary_exists = get_element_by_name(egeria_client, "Glossary", glossary)
1684
1694
  msg = f"Found glossary `{glossary}` with GUID {glossary_guid}"
@@ -1892,6 +1902,58 @@ def process_glossary_list_command(egeria_client: EgeriaTech, txt: str, directive
1892
1902
  return None
1893
1903
 
1894
1904
 
1905
+ def process_term_details_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1906
+ """ List terms as a markdown table. Filter based on optional search string. """
1907
+ set_debug_level(directive)
1908
+ valid = True
1909
+ command = extract_command(txt)
1910
+ object_type = command.split(' ')[1].strip()
1911
+ object_action = command.split(' ')[0].strip()
1912
+
1913
+
1914
+ term_identifier = process_simple_attribute(txt, TERM_NAME_LABELS, "ERROR")
1915
+
1916
+ print(Markdown(f"{pre_command} `{command}` for term:`{term_identifier}` with directive: `{directive}`"))
1917
+
1918
+ output_format = process_simple_attribute(txt, OUTPUT_LABELS, "INFO")
1919
+ if output_format is None:
1920
+ output_format = "REPORT"
1921
+ else:
1922
+ output_format = output_format.upper()
1923
+
1924
+ if output_format not in ["DICT", "REPORT"]:
1925
+ valid = False
1926
+ print_msg(ERROR, f"Invalid output format: `{output_format}`", debug_level)
1927
+
1928
+ request_display = f"\n\t* Term Identifier: {term_identifier}\n\t* Output Format {output_format}"
1929
+
1930
+ if directive == "display":
1931
+ print(request_display)
1932
+ return None
1933
+ elif directive == "validate":
1934
+ print(request_display)
1935
+ return valid
1936
+ elif directive == "process":
1937
+ try:
1938
+ print(request_display)
1939
+ if not valid: # First validate the term before we process it
1940
+ return None
1941
+ output = egeria_client.get_term_details(term_identifier, output_format=output_format)
1942
+ if output_format == "DICT":
1943
+ output = f"```{json.dumps(output, indent=4)}```"
1944
+ print_msg("ALWAYS", f"Wrote Term Details for term: `{term_identifier}`", debug_level)
1945
+
1946
+ return output
1947
+
1948
+ except Exception as e:
1949
+ print(f"{ERROR}Error performing {command}: {e}")
1950
+ console.print_exception(show_locals=True)
1951
+ return None
1952
+ else:
1953
+ return None
1954
+
1955
+
1956
+
1895
1957
  def process_term_history_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
1896
1958
  """ List terms as a markdown table. Filter based on optional search string. """
1897
1959
  set_debug_level(directive)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyegeria
3
- Version: 5.3.8.10
3
+ Version: 5.3.9.1
4
4
  Summary: A python client for Egeria
5
5
  License: Apache 2.0
6
6
  Keywords: egeria,metadata,governance
@@ -1,5 +1,5 @@
1
1
  pyegeria/README.md,sha256=PwX5OC7-YSZUCIsoyHh1O-WBM2hE84sm3Bd4O353NOk,1464
2
- pyegeria/__init__.py,sha256=kqNIJb2ZvIoBXDZwfoCj92C2J6gSVyfgvt0WQnKN_EE,30764
2
+ pyegeria/__init__.py,sha256=Oqge4nZQv6-9TRx8UaC2cj8YKkaIJzjo0ySRfbqlwFI,30793
3
3
  pyegeria/_client.py,sha256=lCWq8XJOFg3MnEO4ulMVuCJrW3uU4eWUCcbLEd90_LU,34673
4
4
  pyegeria/_deprecated_gov_engine.py,sha256=dWNcwVsE5__dF2u4QiIyQrssozzzOjBbLld8MdpmVCQ,17264
5
5
  pyegeria/_exceptions.py,sha256=1SrnV194V4_YJNnNAU0myTHQ3dhLn4GF2B2gZcj1u90,18153
@@ -16,7 +16,7 @@ pyegeria/commands/cat/README.md,sha256=-aaAnIT2fcfU63vajgB-RzQk4l4yFdhkyVfSaTPiq
16
16
  pyegeria/commands/cat/__init__.py,sha256=5OCy4m_yZsnSxdy_gvkCyP_OkjvuWKimqUGHYCJc_qA,450
17
17
  pyegeria/commands/cat/dr_egeria_inbox/glossary_creation_experiment.ipynb,sha256=dbzNu90fCKNohOWVSRBOB1GLyd95x8Qw51I5AkaPtso,11552
18
18
  pyegeria/commands/cat/dr_egeria_jupyter.py,sha256=h9LmDmejmaPDlDuGNlVor-bqNnKPvSBhcC7JFWBdOEM,5710
19
- pyegeria/commands/cat/dr_egeria_md.py,sha256=OCY1tu6NMi0-rTCTOuiRw6wHGZYNY9iS-XmCYRMoC0s,11610
19
+ pyegeria/commands/cat/dr_egeria_md.py,sha256=6Pamoku_psDqrfK5TdAfJIcFU2stUmsnpR-lEkLEsr0,11789
20
20
  pyegeria/commands/cat/exp_list_glossaries.py,sha256=dC6Bnfm3YSMTKPP146qeslIFRiZnGu5b7iDYE07p4iU,5817
21
21
  pyegeria/commands/cat/get_asset_graph.py,sha256=xnXJfpDTVH1TJ2TwE3dtjaXU36Di6-N6JAyhothzz2o,12461
22
22
  pyegeria/commands/cat/get_collection.py,sha256=kXPcP8u-SMWfrVyyBhNoxG8mcgB7EV_5i9N9w_IBU7o,5379
@@ -36,7 +36,7 @@ pyegeria/commands/cat/list_glossaries.py,sha256=D2ovkffSmnO-NQ7y-Jw0aDBtK2j06CQz
36
36
  pyegeria/commands/cat/list_projects.py,sha256=NzWTuepTGUEyxK-eWvuUxtBgCtNWubVwmz2eqm2UN1c,7997
37
37
  pyegeria/commands/cat/list_tech_type_elements.py,sha256=-9omj5en9dSP1xMSljYVHyfXsuhuE1bO2IFj_bZPhAs,6873
38
38
  pyegeria/commands/cat/list_tech_types.py,sha256=uqZcXHCzAznhEG6WWeM5j-spwUh8ycygFqpVDeXOG-0,4653
39
- pyegeria/commands/cat/list_terms.py,sha256=HPZ_S_5EwJezdgf8UY1dZiDbN5P9aD88pI_rBHftm1M,12185
39
+ pyegeria/commands/cat/list_terms.py,sha256=GoGfvJ7W5KoFDc0b15F7RMr2EM2vo4rKHgpGmELjQL0,12259
40
40
  pyegeria/commands/cat/list_todos.py,sha256=NitCw0uyVVjmN1hxb1W-I4FbOsa8wQxW2ICyOElHyc8,6556
41
41
  pyegeria/commands/cat/list_user_ids.py,sha256=X5Q-YNEp38saPYDuy9VwdQC5Qpa4HyC3WvAdbyp_P6M,5108
42
42
  pyegeria/commands/cli/__init__.py,sha256=hpTVSMP2gnPRhcAZPdeUEsQ-eaDySlXlk239dNWYmng,292
@@ -226,11 +226,11 @@ pyegeria/egeria_my_client.py,sha256=eOKLk2zdI6FHZnhAimfR_0yNdBjpUgD41dJZcJODcqE,
226
226
  pyegeria/egeria_tech_client.py,sha256=uycgYfCpb4jzFfaQ7I5JxbZ5PKsWdaWxLOJjbw6C2Zk,3817
227
227
  pyegeria/feedback_manager_omvs.py,sha256=0xBs0p54vmdfVYYgQ8pOanLC4fxfgTk1Z61Y6D1U7_I,152978
228
228
  pyegeria/full_omag_server_config.py,sha256=CQqLCy_3DZFvJZEOcGf50HWdFaWpiAIs6z-kKyjvpDA,47464
229
- pyegeria/glossary_browser_omvs.py,sha256=oxOch569LtyQA35sROtXjS_XAVD4Ek-2ApiqFoKRZRQ,161667
229
+ pyegeria/glossary_browser_omvs.py,sha256=QXjr1tLmxXz81wW4MpiY3PhzBY4tHdIgV2KC5pD0ikc,172375
230
230
  pyegeria/glossary_manager_omvs.py,sha256=aGYZFuzWrPmPLLNwkNpV7-FsalqwDR7gyBzgdubnM04,87989
231
231
  pyegeria/m_test.py,sha256=M5-M2ZczsAJLXWfSeqTTADHdx6Ku-y4PbQ4M21JthAE,7778
232
232
  pyegeria/md_processing_helpers.py,sha256=sV-ciVg_xOGVGTH_CMpH2B5k3V5jzdFp_XvnQQ5xafw,2131
233
- pyegeria/md_processing_utils.py,sha256=wLt-lOxyVuMJr_JN90qJsbt9xD7eCexu_icGuPZqL5E,94233
233
+ pyegeria/md_processing_utils.py,sha256=AbCw8Hr4hIiwRX5pxY9IJGTNlogbdF0tyovt3mmNpxo,96992
234
234
  pyegeria/md_processing_utils_orig.py,sha256=64eVP86__zI4EdzwveskDyLiw6EyWJXZW4pqk9aLpuM,52486
235
235
  pyegeria/mermaid_utilities.py,sha256=sQqdFUWdNpHu9d3Tk9UVe80M-5bOzses0XcFYX5FF-E,54254
236
236
  pyegeria/metadata_explorer_omvs.py,sha256=xHnZTQKbd6XwOhYia-RiIisrvZcqHi0SL1l6OCf04Gk,86911
@@ -245,8 +245,8 @@ pyegeria/template_manager_omvs.py,sha256=chBljs1vy5wr9DRAtbvIt4Cob_7HxGfxLkCNlDT
245
245
  pyegeria/utils.py,sha256=GCt1C0bp0Xng1ahzbZhzV9qQwH7Dj93IaCt2dvWb-sg,5417
246
246
  pyegeria/valid_metadata_omvs.py,sha256=Xq9DqBQvBFFJzaFIRKcVZ2k4gJvSh9yeXs_j-O3vn1w,65050
247
247
  pyegeria/x_action_author_omvs.py,sha256=RcqSzahUKCtvb_3u_wyintAlc9WFkC_2v0E12TZs8lQ,6433
248
- pyegeria-5.3.8.10.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
249
- pyegeria-5.3.8.10.dist-info/METADATA,sha256=_RPRxspNSRd8BtM8mymkGp6VvPRDVAWRMTnvSMjIUks,2758
250
- pyegeria-5.3.8.10.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
251
- pyegeria-5.3.8.10.dist-info/entry_points.txt,sha256=eAvQ_vkejlF3JzMzEc5VD93ymLA_hSFV0HM8fntG-d8,6791
252
- pyegeria-5.3.8.10.dist-info/RECORD,,
248
+ pyegeria-5.3.9.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
249
+ pyegeria-5.3.9.1.dist-info/METADATA,sha256=TDFkuc1HYbzt76TyjjdKAIyNf_gv9Bmr1z5v61h0HMk,2757
250
+ pyegeria-5.3.9.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
251
+ pyegeria-5.3.9.1.dist-info/entry_points.txt,sha256=eAvQ_vkejlF3JzMzEc5VD93ymLA_hSFV0HM8fntG-d8,6791
252
+ pyegeria-5.3.9.1.dist-info/RECORD,,