pyegeria 5.3.8.10__py3-none-any.whl → 5.3.9.2__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.
@@ -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
@@ -131,17 +132,20 @@ class GlossaryBrowser(Client):
131
132
  categories = self.get_categories_for_glossary(guid)
132
133
  cat_md_display = ''
133
134
  cat_md_qn = ''
135
+ category_names = ''
136
+ category_qualified_names = ''
137
+
134
138
  if type(categories) is list:
135
139
  for category in categories:
136
140
  cat_md_display += f" {category['glossaryCategoryProperties'][('displayName')]},\n"
137
141
  cat_md_qn += f" {category['glossaryCategoryProperties'][('qualifiedName')]},\n"
138
- cat_md = cat_md_display.strip()
139
- cat_md_qn = cat_md_qn.strip()
142
+ category_names = cat_md_display.rstrip(',')
143
+ category_qualified_names = cat_md_qn.rstrip(',')
140
144
 
141
145
  return {
142
146
  'guid': guid, 'properties': properties, 'display_name': display_name, 'description': description,
143
- 'language': language, 'usage': usage, 'qualified_name': qualified_name, 'categories_dn_md': cat_md_display,
144
- 'categories_qn_md': cat_md_qn
147
+ 'language': language, 'usage': usage, 'qualified_name': qualified_name, 'categories_names': category_names,
148
+ 'categories_qualified_names': category_qualified_names
145
149
  }
146
150
 
147
151
  def _generate_entity_md(self, elements: list, elements_action: str, output_format: str, entity_type: str,
@@ -181,16 +185,16 @@ class GlossaryBrowser(Client):
181
185
 
182
186
  # Add common attributes
183
187
  for key, value in props.items():
184
- # Skip categories_dn_md for FORM output and categories_qn_md for REPORT output
185
- if key == 'categories_dn_md' and output_format == 'FORM':
188
+ # Skip categories_names for FORM output and categories_qualified_names for REPORT output
189
+ if key == 'categories_names' and output_format == 'FORM':
186
190
  continue
187
- if key == 'categories_qn_md' and output_format == 'REPORT':
191
+ if key == 'categories_qualified_names' and output_format == 'REPORT':
188
192
  continue
189
193
  if key not in ['guid', 'properties', 'display_name']:
190
- # Use "Categories" as the label for both categories_qn_md and categories_dn_md
191
- if key == 'categories_qn_md' and output_format == 'FORM':
194
+ # Use "Categories" as the label for both categories_qualified_names and categories_names
195
+ if key == 'categories_qualified_names' and output_format == 'FORM':
192
196
  elements_md += self.make_md_attribute("Categories", value, output_format)
193
- elif key == 'categories_dn_md' and output_format == 'REPORT':
197
+ elif key == 'categories_names' and output_format == 'REPORT':
194
198
  elements_md += self.make_md_attribute("Categories", value, output_format)
195
199
  else:
196
200
  elements_md += self.make_md_attribute(key.replace('_', ' '), value, output_format)
@@ -222,7 +226,8 @@ class GlossaryBrowser(Client):
222
226
  str: Markdown representation
223
227
  """
224
228
  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)
229
+ entity_type="Glossary",
230
+ extract_properties_func=self._extract_glossary_properties)
226
231
 
227
232
  def _generate_entity_md_table(self, elements: list, search_string: str, entity_type: str, extract_properties_func,
228
233
  columns: list, get_additional_props_func=None, output_format: str = 'LIST') -> str:
@@ -302,14 +307,15 @@ class GlossaryBrowser(Client):
302
307
  str: Markdown table
303
308
  """
304
309
  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}, ]
310
+ {'name': 'Qualified Name', 'key': 'qualified_name'},
311
+ {'name': 'Language', 'key': 'language', 'format': True},
312
+ {'name': 'Description', 'key': 'description', 'format': True},
313
+ {'name': 'Usage', 'key': 'usage', 'format': True},
314
+ {'name': 'Categories', 'key': 'categories_names', 'format': True}, ]
310
315
 
311
316
  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)
317
+ extract_properties_func=self._extract_glossary_properties,
318
+ columns=columns)
313
319
 
314
320
  def _generate_entity_dict(self, elements: list, extract_properties_func, get_additional_props_func=None,
315
321
  include_keys=None, exclude_keys=None, output_format: str = 'DICT') -> list:
@@ -368,7 +374,7 @@ class GlossaryBrowser(Client):
368
374
  list: List of glossary dictionaries
369
375
  """
370
376
  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)
377
+ exclude_keys=['properties', 'categories_qualified_names'], output_format=output_format)
372
378
 
373
379
  def generate_glossaries_md(self, elements: list | dict, search_string: str,
374
380
  output_format: str = 'MD') -> str | list:
@@ -426,9 +432,9 @@ class GlossaryBrowser(Client):
426
432
  aliases = ", ".join(properties.get("aliases", "")) or ""
427
433
 
428
434
  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
435
+ 'guid': guid, 'properties': properties, 'display_name': display_name, 'aliases': aliases,
436
+ 'summary': summary, 'description': description, 'examples': examples, 'usage': usage,
437
+ 'version identifier': pub_version, 'qualified_name': qualified_name, 'status': status
432
438
  }
433
439
 
434
440
  def _get_categories_for_term(self, term_guid: str, output_format: str = None) -> tuple[list, str]:
@@ -449,7 +455,7 @@ class GlossaryBrowser(Client):
449
455
 
450
456
  category_list = self.get_categories_for_term(term_guid)
451
457
  if type(category_list) is str and category_list == NO_CATEGORIES_FOUND:
452
- category_list_md = '---'
458
+ category_list_md = ''
453
459
  elif isinstance(category_list, list) and len(category_list) > 0:
454
460
  first_cat = True
455
461
  for category in category_list:
@@ -507,16 +513,17 @@ class GlossaryBrowser(Client):
507
513
  str: Markdown table
508
514
  """
509
515
  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}]
516
+ {'name': 'Aliases', 'key': 'aliases', 'format': True},
517
+ {'name': 'Summary', 'key': 'summary', 'format': True}, {'name': 'Glossary', 'key': 'glossary'},
518
+ {'name': 'Categories', 'key': 'categories_str', 'format': True}]
512
519
 
513
520
  # Create a wrapper function to pass output_format to _get_term_table_properties
514
521
  def get_table_props_with_format(element, term_guid, output_format_param=None):
515
522
  return self._get_term_table_properties(element, term_guid, output_format)
516
523
 
517
524
  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)
525
+ extract_properties_func=self._extract_term_properties, columns=columns,
526
+ get_additional_props_func=get_table_props_with_format)
520
527
 
521
528
  def _get_term_dict_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
522
529
  """
@@ -558,9 +565,10 @@ class GlossaryBrowser(Client):
558
565
  return self._get_term_dict_properties(element, term_guid, output_format)
559
566
 
560
567
  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
- )
568
+ get_additional_props_func=get_dict_props_with_format,
569
+ exclude_keys=['properties', 'pub_version']
570
+ # Exclude raw properties and pub_version (renamed to version)
571
+ )
564
572
 
565
573
  def _get_term_additional_properties(self, element: dict, term_guid: str, output_format: str = None) -> dict:
566
574
  """
@@ -597,8 +605,8 @@ class GlossaryBrowser(Client):
597
605
  str: Markdown representation
598
606
  """
599
607
  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)
608
+ entity_type="Term", extract_properties_func=self._extract_term_properties,
609
+ get_additional_props_func=self._get_term_additional_properties)
602
610
 
603
611
  def generate_terms_md(self, elements: list | dict, search_string: str, output_format: str = 'MD') -> str | list:
604
612
  """
@@ -776,17 +784,18 @@ class GlossaryBrowser(Client):
776
784
  str: Markdown table
777
785
  """
778
786
  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}]
787
+ {'name': 'Description', 'key': 'description', 'format': True},
788
+ {'name': 'Qualified Name', 'key': 'qualified_name'},
789
+ {'name': 'Parent Category', 'key': 'parent_category'},
790
+ {'name': 'Subcategories', 'key': 'subcategories', 'format': True}]
782
791
 
783
792
  # Create a wrapper function to pass output_format to _get_category_table_properties
784
793
  def get_table_props_with_format(element, category_guid, output_format_param=None):
785
794
  return self._get_category_table_properties(element, category_guid, output_format)
786
795
 
787
796
  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)
797
+ extract_properties_func=self._extract_category_properties,
798
+ columns=columns, get_additional_props_func=get_table_props_with_format)
790
799
 
791
800
  def _get_category_dict_properties(self, element: dict, category_guid: str, output_format: str = None) -> dict:
792
801
  """
@@ -830,8 +839,9 @@ class GlossaryBrowser(Client):
830
839
  return self._get_category_dict_properties(element, category_guid, output_format)
831
840
 
832
841
  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)
842
+ get_additional_props_func=get_dict_props_with_format,
843
+ exclude_keys=['properties'], # Exclude raw properties
844
+ output_format=output_format)
835
845
 
836
846
  def _get_category_additional_properties(self, element: dict, category_guid: str, output_format: str = None) -> dict:
837
847
  """
@@ -882,8 +892,9 @@ class GlossaryBrowser(Client):
882
892
  return self._get_category_additional_properties(element, category_guid, output_format)
883
893
 
884
894
  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)
895
+ entity_type="Category",
896
+ extract_properties_func=self._extract_category_properties,
897
+ get_additional_props_func=get_additional_props_with_format)
887
898
 
888
899
  def generate_categories_md(self, elements: list | dict, search_string: str,
889
900
  output_format: str = 'MD') -> str | list:
@@ -1079,9 +1090,9 @@ class GlossaryBrowser(Client):
1079
1090
  #
1080
1091
 
1081
1092
  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:
1093
+ ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1094
+ for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0,
1095
+ page_size: int = None, output_format: str = 'JSON') -> list | str:
1085
1096
  """Retrieve the list of glossary metadata elements that contain the search string. Async version.
1086
1097
  The search string is located in the request body and is interpreted as a plain string.
1087
1098
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1177,9 +1188,9 @@ class GlossaryBrowser(Client):
1177
1188
  return response.json().get("elementList", NO_GLOSSARIES_FOUND)
1178
1189
 
1179
1190
  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:
1191
+ ends_with: bool = False, ignore_case: bool = False, for_lineage: bool = False,
1192
+ for_duplicate_processing: bool = False, type_name: str = None, start_from: int = 0,
1193
+ page_size: int = None, output_format: str = "JSON") -> list | str:
1183
1194
  """Retrieve the list of glossary metadata elements that contain the search string.
1184
1195
  The search string is located in the request body and is interpreted as a plain string.
1185
1196
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1241,12 +1252,12 @@ class GlossaryBrowser(Client):
1241
1252
  loop = asyncio.get_event_loop()
1242
1253
  response = loop.run_until_complete(
1243
1254
  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))
1255
+ for_duplicate_processing, type_name, start_from, page_size, output_format))
1245
1256
 
1246
1257
  return response
1247
1258
 
1248
1259
  async def _async_get_glossary_by_guid(self, glossary_guid: str, effective_time: str = None,
1249
- output_format: str = "JSON") -> dict | str:
1260
+ output_format: str = "JSON") -> dict | str:
1250
1261
  """Retrieves information about a glossary
1251
1262
  Parameters
1252
1263
  ----------
@@ -1338,7 +1349,7 @@ class GlossaryBrowser(Client):
1338
1349
  return response
1339
1350
 
1340
1351
  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:
1352
+ page_size: int = None, ) -> dict | str:
1342
1353
  """Retrieve the list of glossary metadata elements with an exactly matching qualified or display name.
1343
1354
  There are no wildcards supported on this request.
1344
1355
 
@@ -1391,7 +1402,7 @@ class GlossaryBrowser(Client):
1391
1402
  return response.json().get("elementList", "No glossaries found")
1392
1403
 
1393
1404
  def get_glossaries_by_name(self, glossary_name: str, effective_time: str = None, start_from: int = 0,
1394
- page_size: int = None, ) -> dict | str:
1405
+ page_size: int = None, ) -> dict | str:
1395
1406
  """Retrieve the list of glossary metadata elements with an exactly matching qualified or display name.
1396
1407
  There are no wildcards supported on this request.
1397
1408
 
@@ -1435,7 +1446,7 @@ class GlossaryBrowser(Client):
1435
1446
  #
1436
1447
 
1437
1448
  async def _async_get_glossary_for_category(self, glossary_category_guid: str,
1438
- effective_time: str = None, ) -> dict | str:
1449
+ effective_time: str = None, ) -> dict | str:
1439
1450
  """Retrieve the glossary metadata element for the requested category. The optional request body allows you to
1440
1451
  specify that the glossary element should only be returned if it was effective at a particular time.
1441
1452
 
@@ -1514,8 +1525,9 @@ class GlossaryBrowser(Client):
1514
1525
  return response
1515
1526
 
1516
1527
  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:
1528
+ start_from: int = 0, page_size: int = max_paging_size,
1529
+ for_lineage: bool = False,
1530
+ for_duplicate_processing: bool = False, ) -> dict | str:
1519
1531
  """Glossary categories can be organized in a hierarchy. Retrieve the subcategories for the glossary category
1520
1532
  metadata element with the supplied unique identifier. If the requested category does not have any subcategories,
1521
1533
  null is returned. The optional request body contain an effective time for the query.
@@ -1571,10 +1583,9 @@ class GlossaryBrowser(Client):
1571
1583
 
1572
1584
  return response.json().get("elementList", "No categories found")
1573
1585
 
1574
-
1575
1586
  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:
1587
+ page_size: int = max_paging_size, for_lineage: bool = False,
1588
+ for_duplicate_processing: bool = False, ) -> dict | str:
1578
1589
  """Glossary categories can be organized in a hierarchy. Retrieve the subcategories for the glossary category
1579
1590
  metadata element with the supplied unique identifier. If the requested category does not have any subcategories,
1580
1591
  null is returned. The optional request body contain an effective time for the query.
@@ -1615,12 +1626,13 @@ class GlossaryBrowser(Client):
1615
1626
  loop = asyncio.get_event_loop()
1616
1627
  response = loop.run_until_complete(
1617
1628
  self._async_get_glossary_subcategories(glossary_category_guid, effective_time, start_from, page_size,
1618
- for_lineage, for_duplicate_processing))
1629
+ for_lineage, for_duplicate_processing))
1619
1630
  return response
1620
1631
 
1621
1632
  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:
1633
+ starts_with: bool = False, ends_with: bool = False,
1634
+ ignore_case: bool = False, start_from: int = 0, page_size: int = None,
1635
+ output_format: str = "JSON") -> list | str:
1624
1636
  """Retrieve the list of glossary category metadata elements that contain the search string.
1625
1637
  The search string is located in the request body and is interpreted as a plain string.
1626
1638
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1704,8 +1716,8 @@ class GlossaryBrowser(Client):
1704
1716
  return response.json().get("elementList", NO_CATEGORIES_FOUND)
1705
1717
 
1706
1718
  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:
1719
+ ends_with: bool = False, ignore_case: bool = False, start_from: int = 0,
1720
+ page_size: int = None, output_format: str = "JSON") -> list | str:
1709
1721
  """Retrieve the list of glossary category metadata elements that contain the search string.
1710
1722
  The search string is located in the request body and is interpreted as a plain string.
1711
1723
  The request parameters, startsWith, endsWith and ignoreCase can be used to allow a fuzzy search.
@@ -1759,12 +1771,12 @@ class GlossaryBrowser(Client):
1759
1771
  loop = asyncio.get_event_loop()
1760
1772
  response = loop.run_until_complete(
1761
1773
  self._async_find_glossary_categories(search_string, effective_time, starts_with, ends_with, ignore_case,
1762
- start_from, page_size, output_format))
1774
+ start_from, page_size, output_format))
1763
1775
 
1764
1776
  return response
1765
1777
 
1766
1778
  async def _async_get_categories_for_glossary(self, glossary_guid: str, start_from: int = 0,
1767
- page_size: int = None, ) -> list | str:
1779
+ page_size: int = None, ) -> list | str:
1768
1780
  """Return the list of categories associated with a glossary.
1769
1781
  Async version.
1770
1782
 
@@ -1807,7 +1819,7 @@ class GlossaryBrowser(Client):
1807
1819
  return response.json().get("elementList", "No Categories found")
1808
1820
 
1809
1821
  def get_categories_for_glossary(self, glossary_guid: str, start_from: int = 0,
1810
- page_size: int = None, ) -> list | str:
1822
+ page_size: int = None, ) -> list | str:
1811
1823
  """Return the list of categories associated with a glossary.
1812
1824
 
1813
1825
  Parameters
@@ -1844,7 +1856,7 @@ class GlossaryBrowser(Client):
1844
1856
  return response
1845
1857
 
1846
1858
  async def _async_get_categories_for_term(self, glossary_term_guid: str, start_from: int = 0,
1847
- page_size: int = None, ) -> list | str:
1859
+ page_size: int = None, ) -> list | str:
1848
1860
  """Return the list of categories associated with a glossary term.
1849
1861
  Async version.
1850
1862
 
@@ -1883,10 +1895,10 @@ class GlossaryBrowser(Client):
1883
1895
  f"{glossary_term_guid}/categories/retrieve?startFrom={start_from}&pageSize={page_size}")
1884
1896
 
1885
1897
  response = await self._async_make_request("POST", url)
1886
- return response.json().get("elementList", "No Categories found")
1898
+ return response.json().get("elementList", NO_CATEGORIES_FOUND)
1887
1899
 
1888
1900
  def get_categories_for_term(self, glossary_term_guid: str, start_from: int = 0,
1889
- page_size: int = None, ) -> list | str:
1901
+ page_size: int = None, ) -> list | str:
1890
1902
  """Return the list of categories associated with a glossary term.
1891
1903
 
1892
1904
  Parameters
@@ -1922,7 +1934,7 @@ class GlossaryBrowser(Client):
1922
1934
  return response
1923
1935
 
1924
1936
  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:
1937
+ start_from: int = 0, page_size: int = None, ) -> list | str:
1926
1938
  """Retrieve the list of glossary category metadata elements that either have the requested qualified name or
1927
1939
  display name. The name to search for is located in the request body and is interpreted as a plain string.
1928
1940
  The request body also supports the specification of a glossaryGUID to restrict the search to within a single
@@ -1936,12 +1948,8 @@ class GlossaryBrowser(Client):
1936
1948
  category name to search for.
1937
1949
  glossary_guid: str, optional
1938
1950
  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
1951
  start_from: int, [default=0], optional
1944
- When multiple pages of results are available, the page number to start from.
1952
+ When multiple pages of results are available, the page number to start from.
1945
1953
  page_size: int, [default=None]
1946
1954
  The number of items to return in a single page. If not specified, the default will be taken from
1947
1955
  the class instance.
@@ -1980,7 +1988,7 @@ class GlossaryBrowser(Client):
1980
1988
  return response.json().get("elementList", NO_CATEGORIES_FOUND)
1981
1989
 
1982
1990
  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:
1991
+ start_from: int = 0, page_size: int = None) -> list | str:
1984
1992
  """Retrieve the list of glossary category metadata elements that either have the requested qualified name or
1985
1993
  display name. The name to search for is located in the request body and is interpreted as a plain string.
1986
1994
  The request body also supports the specification of a glossaryGUID to restrict the search to within a
@@ -1992,10 +2000,6 @@ class GlossaryBrowser(Client):
1992
2000
  category name to search for.
1993
2001
  glossary_guid: str, optional
1994
2002
  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
2003
  start_from: int, [default=0], optional
2000
2004
  When multiple pages of results are available, the page number to start from.
2001
2005
  page_size: int, [default=None]
@@ -2287,18 +2291,13 @@ class GlossaryBrowser(Client):
2287
2291
  parent_guid = parent['elementHeader']['guid']
2288
2292
  parent_name = parent['glossaryCategoryProperties'].get('displayName', '---')
2289
2293
  parent_info = {
2290
- 'guid': parent_guid,
2291
- 'name': parent_name
2292
- }
2294
+ 'guid': parent_guid, 'name': parent_name
2295
+ }
2293
2296
 
2294
2297
  return {
2295
- 'guid': category_guid,
2296
- 'name': display_name,
2297
- 'qualifiedName': qualified_name,
2298
- 'description': description,
2299
- 'parent': parent_info,
2300
- 'children': children
2301
- }
2298
+ 'guid': category_guid, 'name': display_name, 'qualifiedName': qualified_name,
2299
+ 'description': description, 'parent': parent_info, 'children': children
2300
+ }
2302
2301
 
2303
2302
  # Build tree for each root category
2304
2303
  for root_guid in root_guids:
@@ -2309,9 +2308,8 @@ class GlossaryBrowser(Client):
2309
2308
  # Format the output according to the specified output_format
2310
2309
  if output_format == "DICT":
2311
2310
  return {
2312
- 'glossary_guid': glossary_guid,
2313
- 'categories': category_tree
2314
- }
2311
+ 'glossary_guid': glossary_guid, 'categories': category_tree
2312
+ }
2315
2313
  elif output_format == "LIST":
2316
2314
  # Generate markdown table
2317
2315
  md_table = "| Category | Path | Description | Parent Category | Child Categories |\n"
@@ -2333,7 +2331,9 @@ class GlossaryBrowser(Client):
2333
2331
  child_names.append(child['name'])
2334
2332
  child_categories = ", ".join(child_names) if child_names else "None"
2335
2333
 
2336
- md_table += f"| {category['name']} | {category_path} | {self._format_for_markdown_table(category['description'])} | {parent_name} | {child_categories} |\n"
2334
+ md_table += (f"| {category['name']} | {category_path} | "
2335
+ f"{self._format_for_markdown_table(category['description'])} | "
2336
+ f"{parent_name} | {child_categories} |\n")
2337
2337
  if category['children']:
2338
2338
  add_categories_to_table(category['children'], category_path)
2339
2339
 
@@ -2365,14 +2365,12 @@ class GlossaryBrowser(Client):
2365
2365
  else:
2366
2366
  return f"Unsupported output format: {output_format}. Use 'DICT', 'LIST', or 'MD'."
2367
2367
 
2368
-
2369
-
2370
2368
  #
2371
2369
  # Terms
2372
2370
  #
2373
2371
 
2374
2372
  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:
2373
+ start_from: int = 0, page_size: int = None, ) -> list | str:
2376
2374
  """Retrieve ALL the glossary terms in a category.
2377
2375
  The request body also supports the specification of an effective time for the query.
2378
2376
 
@@ -2423,7 +2421,7 @@ class GlossaryBrowser(Client):
2423
2421
  return response.json().get("elementList", "No terms found")
2424
2422
 
2425
2423
  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:
2424
+ page_size: int = None, ) -> list | str:
2427
2425
  """Retrieve ALL the glossary terms in a category.
2428
2426
  The request body also supports the specification of an effective time for the query.
2429
2427
 
@@ -2464,7 +2462,7 @@ class GlossaryBrowser(Client):
2464
2462
  return response
2465
2463
 
2466
2464
  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:
2465
+ page_size: int = None, ) -> list | str:
2468
2466
  """Retrieve the list of glossary terms associated with a glossary.
2469
2467
  The request body also supports the specification of an effective time for the query.
2470
2468
  Parameters
@@ -2513,7 +2511,7 @@ class GlossaryBrowser(Client):
2513
2511
  return response.json().get("elementList", "No terms found")
2514
2512
 
2515
2513
  def get_terms_for_glossary(self, glossary_guid: str, effective_time: str = None, start_from: int = 0,
2516
- page_size: int = None, ) -> list | str:
2514
+ page_size: int = None, ) -> list | str:
2517
2515
  """Retrieve the list of glossary terms associated with a glossary.
2518
2516
  The request body also supports the specification of an effective time for the query.
2519
2517
  Parameters
@@ -2551,7 +2549,7 @@ class GlossaryBrowser(Client):
2551
2549
  return response
2552
2550
 
2553
2551
  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:
2552
+ page_size: int = None, output_format: str = "JSON") -> list | str:
2555
2553
  """This call retrieves details of the glossary terms linked to this glossary term.
2556
2554
  Notice the original org 1 glossary term is linked via the "SourcedFrom" relationship.
2557
2555
  Parameters
@@ -2606,12 +2604,11 @@ class GlossaryBrowser(Client):
2606
2604
  elif output_format == 'DICT':
2607
2605
  return None
2608
2606
  if output_format != "JSON": # return a simplified markdown representation
2609
- return self.generate_terms_md(term_elements, term_guid, output_format)
2607
+ return self.generate_related_terms_md(term_elements, term_guid, output_format)
2610
2608
  return response.json().get("elementList", NO_TERMS_FOUND)
2611
2609
 
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:
2610
+ def get_related_terms(self, term_guid: str, effective_time: str = None, start_from: int = 0, page_size: int = None,
2611
+ output_format="JSON") -> list | str:
2615
2612
  """This call retrieves details of the glossary terms linked to this glossary term.
2616
2613
  Notice the original org 1 glossary term is linked via the "SourcedFrom" relationship..
2617
2614
  Parameters
@@ -2644,36 +2641,205 @@ class GlossaryBrowser(Client):
2644
2641
  """
2645
2642
  loop = asyncio.get_event_loop()
2646
2643
  response = loop.run_until_complete(
2647
- self._async_get_related_terms(term_guid, effective_time, start_from,
2648
- page_size, output_format))
2644
+ self._async_get_related_terms(term_guid, effective_time, start_from, page_size, output_format))
2649
2645
 
2650
2646
  return response
2651
2647
 
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
2648
+ def generate_related_terms_md(self, term_elements: list, term_guid: str, output_format: str = 'MD') -> str | list:
2649
+ """
2650
+ Generate a simplified representation of related terms.
2651
+
2652
+ Args:
2653
+ term_elements (list): List of term elements with relationship information
2654
+ term_guid (str): GUID of the term for which to generate related terms
2655
+ output_format (str): Output format (MD, LIST, DICT, etc.)
2654
2656
 
2655
- output_format: str, default = 'JSON'
2657
+ Returns:
2658
+ str | list: Markdown string or list of dictionaries depending on output_format
2659
+ """
2660
+ # Get the first term's display name and qualified name
2661
+ term_name = "Term"
2662
+ try:
2663
+ term_info = self.get_term_by_guid(term_guid, output_format="DICT")
2664
+ # Handle case where term_info is a list of dictionaries
2665
+ if isinstance(term_info, list) and len(term_info) > 0:
2666
+ term_info = term_info[0] # Get the first term
2667
+ if isinstance(term_info, dict) and 'display_name' in term_info:
2668
+ term_name = term_info['display_name']
2669
+ except:
2670
+ # If we can't get the term info, just use the default name
2671
+ pass
2672
+
2673
+ # Create a list to store the simplified related terms
2674
+ related_terms = []
2675
+
2676
+ # Process each term element
2677
+ for element in term_elements:
2678
+ # Extract relationship type from the relationship header
2679
+ relationship_type = element['relatedElement']['relationshipHeader']['type']['typeName']
2680
+
2681
+ # Extract related term information
2682
+ related_term = {
2683
+ 'first_term_display_name': term_name, 'first_term_qualified_name': term_info.get('qualified_name', ''),
2684
+ 'related_term_display_name': element['glossaryTermProperties'].get('displayName', ''),
2685
+ 'related_term_qualified_name': element['glossaryTermProperties'].get('qualifiedName', ''),
2686
+ 'relationship_type': relationship_type
2687
+ }
2688
+
2689
+ related_terms.append(related_term)
2690
+
2691
+ # Return based on output format
2692
+ if output_format == 'DICT':
2693
+ return related_terms
2694
+
2695
+ # For MD, LIST, FORM, REPORT formats, create a markdown representation
2696
+ md_output = f"# Related Terms for {term_name}\n\n"
2697
+
2698
+ if output_format == 'LIST':
2699
+ # Create a table
2700
+ md_output += ("| First Term | First Term Qualified Name | Related Term | Related Term Qualified Name | "
2701
+ "Relationship Type |\n")
2702
+ md_output += \
2703
+ "|------------|---------------------------|--------------|------------------------------|-------------------|\n"
2704
+
2705
+ for term in related_terms:
2706
+ md_output += f"| {term['first_term_display_name']} | {term['first_term_qualified_name']} | "
2707
+ md_output += f"{term['related_term_display_name']} | {term['related_term_qualified_name']} | "
2708
+ md_output += f"{term['relationship_type']} |\n"
2709
+ else:
2710
+ # For other formats, create a more detailed representation
2711
+ for term in related_terms:
2712
+ md_output += f"## {term['relationship_type']} Relationship\n\n"
2713
+ md_output += (f"**First Term:** {term['first_term_display_name']} ("
2714
+ f"{term['first_term_qualified_name']})\n\n")
2715
+ md_output += f"**Related Term:** {term[('related_term_dis'
2716
+ 'play_name')]} ({term['related_term_qualified_name']})\n\n"
2717
+ md_output += "---\n\n"
2718
+
2719
+ return md_output
2720
+
2721
+ def get_term_details(self, term_name: str, effective_time: str = None, output_format: str = 'DICT') -> dict | str:
2722
+ """Retrieve detailed information about a term, combining basic term details and related terms.
2723
+
2724
+ This method combines the term details retrieved from get_term_by_guid and the related terms
2725
+ information from generate_related_terms_md.
2726
+
2727
+ Parameters
2728
+ ----------
2729
+ term_name : str
2730
+ Either the display name or the qualified name of the term to retrieve.
2731
+ effective_time : str, optional
2732
+ Time at which the term is active. If not specified, the current time is used.
2733
+ output_format : str, default = 'DICT'
2656
2734
  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
2735
+ DICT - output a dictionary with combined term details and related terms
2736
+ REPORT - output a markdown report with combined term details and related terms
2737
+
2738
+ Returns
2739
+ -------
2740
+ dict | str
2741
+ A dictionary or markdown string containing the combined term details and related terms.
2742
+
2743
+ Raises
2744
+ ------
2745
+ InvalidParameterException
2746
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values.
2747
+ PropertyServerException
2748
+ Raised by the server when an issue arises in processing a valid request.
2749
+ NotAuthorizedException
2750
+ The principle specified by the user_id does not have authorization for the requested action.
2660
2751
  """
2752
+ # Check if the output format is supported
2753
+ if output_format not in ["DICT", "REPORT"]:
2754
+ return f"Unsupported output format: {output_format}. Supported formats are DICT and REPORT."
2661
2755
 
2756
+ # Search for the term using the qualified name
2757
+ terms = self.get_terms_by_name(term_name, effective_time=effective_time, output_format="DICT")
2662
2758
 
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
2759
+ # Check if we found any terms
2760
+ if not terms or (isinstance(terms, str) and terms == NO_TERMS_FOUND):
2761
+ return f"No term found with name: {term_name}"
2667
2762
 
2668
- related = self.get_related_terms(core[0]['guid'], effective_time)
2669
- if not related:
2670
- return "NO RELATED TERMS FOUND"
2763
+ # Make sure we only have one term
2764
+ if isinstance(terms, list) and len(terms) > 1:
2765
+ return f"Multiple terms found with name: {term_name} - please specify the qualified name."
2671
2766
 
2672
- related_term_guid = related[0]["relatedElement"]["relatedElement"]["guid"]
2673
- related_term_qn = related[0]["relatedElement"]["relatedElement"]["uniquedName"]
2767
+ term_details = terms[0]
2674
2768
 
2769
+ # Get related terms
2770
+ try:
2771
+ related_terms_response = self.get_related_terms(term_details.get('guid', ''), output_format="DICT")
2772
+ except (InvalidParameterException, PropertyServerException, UserNotAuthorizedException):
2773
+ # If we can't get related terms, set to empty list
2774
+ related_terms_response = []
2675
2775
 
2776
+ # If no related terms were found, set to empty list
2777
+ if isinstance(related_terms_response, str) and related_terms_response == NO_TERMS_FOUND:
2778
+ related_terms = []
2779
+ elif related_terms_response is None:
2780
+ related_terms = []
2781
+ else:
2782
+ related_terms = related_terms_response
2676
2783
 
2784
+ # Combine the data
2785
+ if output_format == "DICT":
2786
+ # Create a combined dictionary
2787
+ combined_data = {
2788
+ "term_details": term_details, "related_terms": related_terms
2789
+ }
2790
+ return combined_data
2791
+ elif output_format == "REPORT":
2792
+ # Create a markdown report
2793
+ md_output = f"# Term Details Report for `{term_name}` \n\n"
2794
+
2795
+ # Add term details
2796
+ md_output += "## Basic Term Information\n\n"
2797
+ md_output += f"**Display Name:** {term_details.get('display_name', '')}\n\n"
2798
+ md_output += f"**Qualified Name:** {term_details.get('qualified_name', '')}\n\n"
2799
+ md_output += f"**GUID:** {term_details.get('guid', '')}\n\n"
2800
+
2801
+ if 'summary' in term_details and term_details['summary']:
2802
+ md_output += f"**Summary:** {term_details.get('summary', '')}\n\n"
2803
+
2804
+ if 'description' in term_details and term_details['description']:
2805
+ md_output += f"**Description:** {term_details.get('description', '')}\n\n"
2806
+
2807
+ if 'examples' in term_details and term_details['examples']:
2808
+ md_output += f"**Examples:** {term_details.get('examples', '')}\n\n"
2809
+
2810
+ if 'usage' in term_details and term_details['usage']:
2811
+ md_output += f"**Usage:** {term_details.get('usage', '')}\n\n"
2812
+
2813
+ if 'aliases' in term_details and term_details['aliases']:
2814
+ md_output += f"**Aliases:** {term_details.get('aliases', '')}\n\n"
2815
+
2816
+ if 'status' in term_details and term_details['status']:
2817
+ md_output += f"**Status:** {term_details.get('status', '')}\n\n"
2818
+
2819
+ if 'in_glossary' in term_details and term_details['in_glossary']:
2820
+ md_output += f"**Glossary:** {term_details.get('in_glossary', '')}\n\n"
2821
+
2822
+ if 'categories' in term_details and term_details['categories']:
2823
+ md_output += f"**Categories:** {', '.join(term_details.get('categories', []))}\n\n"
2824
+
2825
+ # Add related terms
2826
+ md_output += "## Related Terms\n\n"
2827
+
2828
+ if not related_terms:
2829
+ md_output += "No related terms found.\n\n"
2830
+ else:
2831
+ # Create a table for related terms
2832
+ md_output += "| Related Term | Qualified Name | Relationship Type |\n"
2833
+ md_output += "|--------------|---------------|-------------------|\n"
2834
+
2835
+ for term in related_terms:
2836
+ md_output += f"| {term.get('related_term_display_name', '')} | "
2837
+ md_output += f"{term.get('related_term_qualified_name', '')} | "
2838
+ md_output += f"{term.get('relationship_type', '')} |\n"
2839
+
2840
+ return md_output
2841
+ else:
2842
+ return f"Unsupported output format: {output_format}. Supported formats are DICT and REPORT."
2677
2843
 
2678
2844
  async def _async_get_glossary_for_term(self, term_guid: str, effective_time: str = None) -> dict | str:
2679
2845
  """Retrieve the glossary metadata element for the requested term. The optional request body allows you to
@@ -2752,8 +2918,9 @@ class GlossaryBrowser(Client):
2752
2918
  return response
2753
2919
 
2754
2920
  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:
2921
+ effective_time: str = None, for_lineage: bool = False,
2922
+ for_duplicate_processing: bool = False, start_from: int = 0,
2923
+ page_size: int = None, output_format="JSON") -> list:
2757
2924
  """Retrieve glossary terms by display name or qualified name. Async Version.
2758
2925
 
2759
2926
  Parameters
@@ -2831,10 +2998,9 @@ class GlossaryBrowser(Client):
2831
2998
  return self.generate_terms_md(term_elements, term, output_format)
2832
2999
  return response.json().get("elementList", NO_TERMS_FOUND)
2833
3000
 
2834
-
2835
3001
  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:
3002
+ effective_time: str = None, for_lineage: bool = False, for_duplicate_processing: bool = False,
3003
+ start_from: int = 0, page_size: int = None, output_format="JSON") -> list:
2838
3004
  """Retrieve glossary terms by display name or qualified name.
2839
3005
 
2840
3006
  Parameters
@@ -2883,7 +3049,7 @@ class GlossaryBrowser(Client):
2883
3049
  loop = asyncio.get_event_loop()
2884
3050
  response = loop.run_until_complete(
2885
3051
  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))
3052
+ for_duplicate_processing, start_from, page_size, output_format))
2887
3053
  return response
2888
3054
 
2889
3055
  async def _async_get_term_by_guid(self, term_guid: str, output_format: str = 'JSON') -> dict | str:
@@ -2960,10 +3126,11 @@ class GlossaryBrowser(Client):
2960
3126
  return response
2961
3127
 
2962
3128
  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,
3129
+ to_time: str = None, oldest_first: bool = False, for_lineage: bool = False,
3130
+ for_duplicate_processing: bool = False, start_from: int = 0,
3131
+ page_size=max_paging_size,
2965
3132
 
2966
- ) -> list | str:
3133
+ ) -> list | str:
2967
3134
  """Retrieve the versions of a glossary term. Async version.
2968
3135
  Parameters
2969
3136
  ----------
@@ -3017,8 +3184,8 @@ class GlossaryBrowser(Client):
3017
3184
  return response.json().get("elementList", "No term found")
3018
3185
 
3019
3186
  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:
3187
+ oldest_first: bool = False, for_lineage: bool = False, for_duplicate_processing: bool = False,
3188
+ start_from: int = 0, page_size=max_paging_size, ) -> dict | str:
3022
3189
  """Retrieve the versions of a glossary term.
3023
3190
  Parameters
3024
3191
  ----------
@@ -3123,7 +3290,7 @@ class GlossaryBrowser(Client):
3123
3290
  return response
3124
3291
 
3125
3292
  async def _async_get_term_revision_history(self, term_revision_log_guid: str, start_from: int = 0,
3126
- page_size=None, ) -> dict | str:
3293
+ page_size=None, ) -> dict | str:
3127
3294
  """Retrieve the revision history for a glossary term. Async version.
3128
3295
 
3129
3296
  Parameters
@@ -3168,7 +3335,7 @@ class GlossaryBrowser(Client):
3168
3335
  return response.json().get("elementList", "No logs found")
3169
3336
 
3170
3337
  def get_term_revision_history(self, term_revision_log_guid: str, start_from: int = 0,
3171
- page_size=None, ) -> dict | str:
3338
+ page_size=None, ) -> dict | str:
3172
3339
  """Retrieve the revision history for a glossary term.
3173
3340
 
3174
3341
  Parameters
@@ -3230,7 +3397,6 @@ class GlossaryBrowser(Client):
3230
3397
  If output_format is "LIST", returns a markdown table of the revision history.
3231
3398
  If no revision logs are found, returns a string message "No revision logs found".
3232
3399
  """
3233
- import re
3234
3400
  validate_guid(term_guid)
3235
3401
 
3236
3402
  # Get revision logs for the term
@@ -3258,15 +3424,15 @@ class GlossaryBrowser(Client):
3258
3424
  update_time = title[keyword_index + 2:].strip()
3259
3425
 
3260
3426
  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
- }
3427
+ 'qualifiedName': qualified_name, 'title': title,
3428
+ 'text': entry.get('properties', {}).get('text', '---'), 'updateTime': update_time
3429
+ # Use extracted date/time or fall back to title
3430
+ }
3266
3431
  all_entries.append(entry_data)
3267
3432
 
3268
3433
  # Sort entries by update time
3269
- sorted_entries = sorted(all_entries, key=lambda x: x['updateTime'] if x['updateTime'] != '---' else '', reverse=True)
3434
+ sorted_entries = sorted(all_entries, key=lambda x: x['updateTime'] if x['updateTime'] != '---' else '',
3435
+ reverse=True)
3270
3436
 
3271
3437
  # Return in the specified format
3272
3438
  if output_format == "DICT":
@@ -3310,7 +3476,6 @@ class GlossaryBrowser(Client):
3310
3476
  # Default to DICT format
3311
3477
  return sorted_entries
3312
3478
 
3313
-
3314
3479
  def list_full_term_history(self, term_guid: str, output_type: str = "DICT") -> list | str:
3315
3480
  """
3316
3481
  Retrieves and formats the entire version history of a specific term in the repository.
@@ -3385,9 +3550,10 @@ class GlossaryBrowser(Client):
3385
3550
  return None
3386
3551
 
3387
3552
  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:
3553
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3554
+ ignore_case: bool = False, for_lineage: bool = False,
3555
+ for_duplicate_processing: bool = False, start_from: int = 0,
3556
+ page_size: int = None, output_format: str = "JSON", ) -> list | str:
3391
3557
  """Retrieve the list of glossary term metadata elements that contain the search string.
3392
3558
 
3393
3559
  Parameters
@@ -3486,9 +3652,10 @@ class GlossaryBrowser(Client):
3486
3652
  return response.json().get("elementList", NO_TERMS_FOUND)
3487
3653
 
3488
3654
  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:
3655
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3656
+ ignore_case: bool = False, for_lineage: bool = False,
3657
+ for_duplicate_processing: bool = False, start_from: int = 0, page_size: int = None,
3658
+ output_format: str = "JSON", ) -> list | str:
3492
3659
  """Retrieve the list of glossary term metadata elements that contain the search string.
3493
3660
 
3494
3661
  Parameters
@@ -3553,7 +3720,8 @@ class GlossaryBrowser(Client):
3553
3720
  loop = asyncio.get_event_loop()
3554
3721
  response = loop.run_until_complete(
3555
3722
  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))
3723
+ ends_with, ignore_case, for_lineage, for_duplicate_processing, start_from,
3724
+ page_size, output_format))
3557
3725
 
3558
3726
  return response
3559
3727
 
@@ -3561,7 +3729,7 @@ class GlossaryBrowser(Client):
3561
3729
  # Feedback
3562
3730
  #
3563
3731
  async def _async_get_comment(self, commemt_guid: str, effective_time: str, for_lineage: bool = False,
3564
- for_duplicate_processing: bool = False, ) -> dict | list:
3732
+ for_duplicate_processing: bool = False, ) -> dict | list:
3565
3733
  """Retrieve the comment specified by the comment GUID"""
3566
3734
 
3567
3735
  validate_guid(commemt_guid)
@@ -3584,7 +3752,7 @@ class GlossaryBrowser(Client):
3584
3752
  return response.json()
3585
3753
 
3586
3754
  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:
3755
+ for_lineage: bool = False, for_duplicate_processing: bool = False, ) -> str:
3588
3756
  """Reply to a comment"""
3589
3757
 
3590
3758
  validate_guid(comment_guid)
@@ -3609,7 +3777,8 @@ class GlossaryBrowser(Client):
3609
3777
  return response
3610
3778
 
3611
3779
  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:
3780
+ is_merge_update: bool = False, for_lineage: bool = False,
3781
+ for_duplicate_processing: bool = False, ) -> str:
3613
3782
  """Update the specified comment"""
3614
3783
 
3615
3784
  validate_guid(comment_guid)
@@ -3634,9 +3803,9 @@ class GlossaryBrowser(Client):
3634
3803
  return response
3635
3804
 
3636
3805
  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, ):
3806
+ effective_time: str = None, starts_with: bool = False, ends_with: bool = False,
3807
+ ignore_case: bool = False, for_lineage: bool = False,
3808
+ for_duplicate_processing: bool = False, start_from: int = 0, page_size: int = None, ):
3640
3809
  """Find comments by search string"""
3641
3810
 
3642
3811
  if page_size is None: