pyegeria 5.4.0.dev3__py3-none-any.whl → 5.4.0.dev6__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.
Files changed (58) hide show
  1. commands/cat/dr_egeria_md.py +12 -3
  2. commands/cat/list_collections.py +7 -6
  3. commands/cat/list_data_designer.py +20 -9
  4. md_processing/__init__.py +4 -1
  5. md_processing/data/commands.json +142 -17
  6. md_processing/md_commands/data_designer_commands.py +408 -101
  7. md_processing/md_commands/glossary_commands.py +0 -30
  8. md_processing/md_commands/solution_architect_commands.py +1 -1
  9. md_processing/md_processing_utils/common_md_proc_utils.py +16 -4
  10. md_processing/md_processing_utils/md_processing_constants.py +3 -1
  11. pyegeria/collection_manager_omvs.py +120 -72
  12. pyegeria/data_designer_omvs.py +161 -60
  13. pyegeria/glossary_browser_omvs.py +5 -6
  14. pyegeria/output_formatter.py +33 -14
  15. pyegeria/solution_architect_omvs.py +277 -9
  16. {pyegeria-5.4.0.dev3.dist-info → pyegeria-5.4.0.dev6.dist-info}/METADATA +1 -1
  17. {pyegeria-5.4.0.dev3.dist-info → pyegeria-5.4.0.dev6.dist-info}/RECORD +20 -58
  18. commands/cat/.DS_Store +0 -0
  19. commands/cat/debug_log.2025-06-05_20-24-18_123924.log.zip +0 -0
  20. commands/cat/debug_log.2025-06-10_08-45-03_929921.log.zip +0 -0
  21. commands/cat/debug_log.2025-06-11_09-57-21_247890.log.zip +0 -0
  22. commands/cat/debug_log.2025-06-12_16-14-31_212042.log.zip +0 -0
  23. commands/cat/debug_log.log +0 -1267
  24. commands/cat/solution_architect_log.log +0 -0
  25. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  26. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  27. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  28. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  29. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  30. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  31. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  32. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  33. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  34. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  35. md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
  36. md_processing/dr_egeria_inbox/data_field.md +0 -54
  37. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  38. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2406
  39. md_processing/dr_egeria_inbox/data_test.md +0 -179
  40. md_processing/dr_egeria_inbox/data_test2.md +0 -376
  41. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  42. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  43. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -313
  44. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  45. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  46. md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
  47. md_processing/dr_egeria_inbox/glossary_test1.md +0 -324
  48. md_processing/dr_egeria_inbox/rel.md +0 -8
  49. md_processing/dr_egeria_inbox/sb.md +0 -119
  50. md_processing/dr_egeria_inbox/solution-components.md +0 -129
  51. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  52. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  53. md_processing/dr_egeria_inbox/t1.md +0 -0
  54. md_processing/dr_egeria_inbox/t2.md +0 -268
  55. pyegeria/.DS_Store +0 -0
  56. {pyegeria-5.4.0.dev3.dist-info → pyegeria-5.4.0.dev6.dist-info}/LICENSE +0 -0
  57. {pyegeria-5.4.0.dev3.dist-info → pyegeria-5.4.0.dev6.dist-info}/WHEEL +0 -0
  58. {pyegeria-5.4.0.dev3.dist-info → pyegeria-5.4.0.dev6.dist-info}/entry_points.txt +0 -0
@@ -577,7 +577,7 @@ r replace_all_properties: bool, default = False
577
577
  return None
578
578
  collection_list = {"DictList": [], "SpecList": [], "CollectionDetails": []}
579
579
  if isinstance(data_structure_info, (dict, list)):
580
- member_of_collections = data_structure_info['memberOfCollections']
580
+ member_of_collections = data_structure_info.get('memberOfCollections',"")
581
581
  if isinstance(member_of_collections, list):
582
582
  for member_rel in member_of_collections:
583
583
  props = member_rel["relatedElement"]["properties"]
@@ -624,7 +624,7 @@ r replace_all_properties: bool, default = False
624
624
  return collection_list
625
625
 
626
626
 
627
- def get_data_field_rel_elements_dict(self, field_struct: dict)-> dict | str:
627
+ def get_data_rel_elements_dict(self, el_struct: dict)-> dict | str:
628
628
  """return the lists of objects related to a data field"""
629
629
 
630
630
  parent_guids = []
@@ -653,11 +653,24 @@ r replace_all_properties: bool, default = False
653
653
 
654
654
  member_of_data_spec_guids = []
655
655
  member_of_data_spec_names = []
656
- member_of_data_specs_qnames = []
656
+ member_of_data_spec_qnames = []
657
+
658
+ member_data_field_guids = []
659
+ member_data_field_names = []
660
+ member_data_field_qnames = []
661
+
662
+ nested_data_classes_guids = []
663
+ nested_data_classes_names = []
664
+ nested_data_classes_qnames = []
665
+
666
+ specialized_data_classes_guids = []
667
+ specialized_data_classes_names = []
668
+ specialized_data_classes_qnames = []
669
+
657
670
 
658
671
 
659
672
  # terms
660
- assigned_meanings = field_struct["assignedMeanings"]
673
+ assigned_meanings = el_struct.get("assignedMeanings", {})
661
674
  for meaning in assigned_meanings:
662
675
  assigned_meanings_guids.append(meaning['relatedElement']['elementHeader']['guid'])
663
676
  assigned_meanings_names.append(meaning['relatedElement']['properties']['displayName'])
@@ -665,26 +678,26 @@ r replace_all_properties: bool, default = False
665
678
 
666
679
 
667
680
  # extract existing related data structure and data field elements
668
- other_related_elements = field_struct["otherRelatedElements"]
669
-
670
- for rel in other_related_elements:
671
- related_element = rel["relatedElement"]
672
- type = related_element["elementHeader"]["type"]["typeName"]
673
- guid = related_element["elementHeader"]["guid"]
674
- qualified_name = related_element["properties"].get("qualifiedName","") or ""
675
- display_name = related_element["properties"].get("displayName","") or ""
676
- if type == "DataStructure":
677
- data_structure_guids.append(guid)
678
- data_structure_names.append(display_name)
679
- data_structure_qnames.append(qualified_name)
680
-
681
- elif type == "DataField":
682
- parent_guids.append(guid)
683
- parent_names.append(display_name)
684
- parent_qnames.append(qualified_name)
685
-
686
-
687
- member_of_collections = field_struct["memberOfCollections"]
681
+ other_related_elements = el_struct.get("otherRelatedElements",None)
682
+ if other_related_elements:
683
+ for rel in other_related_elements:
684
+ related_element = rel["relatedElement"]
685
+ type = related_element["elementHeader"]["type"]["typeName"]
686
+ guid = related_element["elementHeader"]["guid"]
687
+ qualified_name = related_element["properties"].get("qualifiedName","") or ""
688
+ display_name = related_element["properties"].get("displayName","") or ""
689
+ if type == "DataStructure":
690
+ data_structure_guids.append(guid)
691
+ data_structure_names.append(display_name)
692
+ data_structure_qnames.append(qualified_name)
693
+
694
+ elif type == "DataField":
695
+ parent_guids.append(guid)
696
+ parent_names.append(display_name)
697
+ parent_qnames.append(qualified_name)
698
+
699
+
700
+ member_of_collections = el_struct.get("memberOfCollections",{})
688
701
  for collection in member_of_collections:
689
702
  c_type = collection["relatedElement"]["properties"].get("collectionType","") or ""
690
703
  guid = collection["relatedElement"]["elementHeader"]["guid"]
@@ -700,7 +713,33 @@ r replace_all_properties: bool, default = False
700
713
  elif type_name == "DataSpec":
701
714
  member_of_data_spec_guids.append(guid)
702
715
  member_of_data_spec_names.append(name)
703
- member_of_data_specs_qnames.append(qualifiedName)
716
+ member_of_data_spec_qnames.append(qualifiedName)
717
+
718
+ member_data_fields = el_struct.get("memberDataFields", {})
719
+ for data_field in member_data_fields:
720
+ member_data_field_guids.append(data_field["elementHeader"]["guid"])
721
+ member_data_field_names.append(data_field["properties"]["displayName"])
722
+ member_data_field_qnames.append(data_field["properties"]["qualifiedName"])
723
+
724
+ data_classes = el_struct.get("assignedDataClasses", {})
725
+ for data_class in data_classes:
726
+ data_class_guids.append(data_class['relatedElement']["elementHeader"]["guid"])
727
+ data_class_names.append(data_class['relatedElement']["properties"]["displayName"])
728
+ data_class_qnames.append(data_class['relatedElement']["properties"]["qualifiedName"])
729
+
730
+ nested_data_classes = el_struct.get("nestedDataClasses", {})
731
+ for nested_data_class in nested_data_classes:
732
+ nested_data_classes_guids.append(nested_data_class['relatedElement']["elementHeader"]["guid"])
733
+ nested_data_classes_names.append(nested_data_class['relatedElement']["properties"]["displayName"])
734
+ nested_data_classes_qnames.append(nested_data_class['relatedElement']["properties"]["qualifiedName"])
735
+
736
+ specialized_data_classes = el_struct.get("specializedDataClasses", {})
737
+ for nested_data_class in specialized_data_classes:
738
+ specialized_data_classes_guids.append(nested_data_class['relatedElement']["elementHeader"]["guid"])
739
+ specialized_data_classes_names.append(nested_data_class['relatedElement']["properties"]["displayName"])
740
+ specialized_data_classes_qnames.append(nested_data_class['relatedElement']["properties"]["qualifiedName"])
741
+
742
+ mermaid = el_struct.get("mermaidGraph", {})
704
743
 
705
744
  return {"parent_guids": parent_guids,
706
745
  "parent_names": parent_names,
@@ -718,6 +757,14 @@ r replace_all_properties: bool, default = False
718
757
  "data_class_names": data_class_names,
719
758
  "data_class_qnames": data_class_qnames,
720
759
 
760
+ "nested_data_class_guids": nested_data_classes_guids,
761
+ "nested_data_class_names": nested_data_classes_names,
762
+ "nested_data_class_qnames": nested_data_classes_qnames,
763
+
764
+ "specialized_data_class_guids": specialized_data_classes_guids,
765
+ "specialized_data_class_names": specialized_data_classes_names,
766
+ "specialized_data_class_qnames": specialized_data_classes_qnames,
767
+
721
768
  "external_references_guids": external_references_guids,
722
769
  "external_references_names": external_references_names,
723
770
  "external_references_qnames": external_references_qnames,
@@ -728,7 +775,13 @@ r replace_all_properties: bool, default = False
728
775
 
729
776
  "member_of_data_spec_guids": member_of_data_spec_guids,
730
777
  "member_of_data_spec_names": member_of_data_spec_names,
731
- "member_of_data_specs_qnames": member_of_data_specs_qnames,
778
+ "member_of_data_spec_qnames": member_of_data_spec_qnames,
779
+
780
+ "member_data_field_guids": member_data_field_guids,
781
+ "member_data_field_names": member_data_field_names,
782
+ "member_data_field_qnames": member_data_field_qnames,
783
+
784
+ "mermaid" : mermaid,
732
785
  }
733
786
 
734
787
 
@@ -737,8 +790,17 @@ r replace_all_properties: bool, default = False
737
790
 
738
791
  data_field_entry = self.get_data_field_by_guid(guid, output_format="JSON")
739
792
  if isinstance(data_field_entry, str):
740
- return NO_ELEMENTS_FOUND
741
- return self.get_data_field_rel_elements_dict(data_field_entry)
793
+ return None
794
+ return self.get_data_rel_elements_dict(data_field_entry)
795
+
796
+ def get_data_class_rel_elements(self, guid:str)-> dict | str:
797
+ """return the lists of objects related to a data class"""
798
+
799
+ data_class_entry = self.get_data_class_by_guid(guid, output_format="JSON")
800
+ if isinstance(data_class_entry, str):
801
+ return None
802
+ return self.get_data_rel_elements_dict(data_class_entry)
803
+
742
804
 
743
805
 
744
806
  async def _async_link_member_data_field(self, parent_data_struct_guid: str, member_data_field_guid: str,
@@ -2526,6 +2588,8 @@ r replace_all_properties: bool, default = False
2526
2588
  }
2527
2589
 
2528
2590
  """
2591
+ if filter == "*":
2592
+ filter = None
2529
2593
  starts_with_s = str(starts_with).lower()
2530
2594
  ends_with_s = str(ends_with).lower()
2531
2595
  ignore_case_s = str(ignore_case).lower()
@@ -2643,7 +2707,8 @@ r replace_all_properties: bool, default = False
2643
2707
  the requesting user is not authorized to issue this request.
2644
2708
 
2645
2709
  """
2646
-
2710
+ if filter == "*":
2711
+ filter = None
2647
2712
  body = {"filter": filter}
2648
2713
  starts_with_s = str(starts_with).lower()
2649
2714
  ends_with_s = str(ends_with).lower()
@@ -3391,7 +3456,7 @@ r replace_all_properties: bool, default = False
3391
3456
  """
3392
3457
  replace_all_properties_s = str(replace_all_properties).lower()
3393
3458
 
3394
- url = (f"{base_path(self, self.view_server)}/data-class/{data_class_guid}/update?"
3459
+ url = (f"{base_path(self, self.view_server)}/data-classes/{data_class_guid}/update?"
3395
3460
  f"replaceAllProperties={replace_all_properties_s}")
3396
3461
 
3397
3462
  await self._async_make_request("POST", url, body_slimmer(body))
@@ -3609,7 +3674,7 @@ r replace_all_properties: bool, default = False
3609
3674
  """
3610
3675
 
3611
3676
  url = (f"{base_path(self, self.view_server)}/data-classes/{parent_data_class_guid}"
3612
- f"/member-data-classes/{child_data_class_guid}/detach")
3677
+ f"/nested-data-classes/{child_data_class_guid}/detach")
3613
3678
 
3614
3679
  if body is None:
3615
3680
  await self._async_make_request("POST", url)
@@ -3708,7 +3773,7 @@ r replace_all_properties: bool, default = False
3708
3773
  """
3709
3774
 
3710
3775
  url = (f"{base_path(self, self.view_server)}/data-classes/{parent_data_class_guid}"
3711
- f"/specializeddata-classes/{child_data_class_guid}/attach")
3776
+ f"/specialized-data-classes/{child_data_class_guid}/attach")
3712
3777
 
3713
3778
  if body is None:
3714
3779
  await self._async_make_request("POST", url)
@@ -3807,7 +3872,7 @@ r replace_all_properties: bool, default = False
3807
3872
  """
3808
3873
 
3809
3874
  url = (f"{base_path(self, self.view_server)}/data-classes/{parent_data_class_guid}"
3810
- f"/specializeddata-classes/{child_data_class_guid}/detach")
3875
+ f"/specialized-data-classes/{child_data_class_guid}/detach")
3811
3876
 
3812
3877
  if body is None:
3813
3878
  await self._async_make_request("POST", url)
@@ -4091,6 +4156,7 @@ r replace_all_properties: bool, default = False
4091
4156
  }
4092
4157
 
4093
4158
  """
4159
+
4094
4160
  starts_with_s = str(starts_with).lower()
4095
4161
  ends_with_s = str(ends_with).lower()
4096
4162
  ignore_case_s = str(ignore_case).lower()
@@ -4208,7 +4274,8 @@ r replace_all_properties: bool, default = False
4208
4274
  the requesting user is not authorized to issue this request.
4209
4275
 
4210
4276
  """
4211
-
4277
+ if filter == "*":
4278
+ filter = None
4212
4279
  body = {"filter": filter}
4213
4280
 
4214
4281
  starts_with_s = str(starts_with).lower()
@@ -4444,7 +4511,7 @@ r replace_all_properties: bool, default = False
4444
4511
  else:
4445
4512
  response: Response = await self._async_make_request("POST", url)
4446
4513
 
4447
- elements = response.json().get("elements", NO_ELEMENTS_FOUND)
4514
+ elements = response.json().get("element", NO_ELEMENTS_FOUND)
4448
4515
  if type(elements) is str:
4449
4516
  return NO_ELEMENTS_FOUND
4450
4517
  if output_format != 'JSON': # return other representations
@@ -5123,15 +5190,20 @@ r replace_all_properties: bool, default = False
5123
5190
  additional_properties = properties.get("additionalProperties", {})
5124
5191
 
5125
5192
  # Now lets get the related elements
5126
- related_elements = self.get_data_field_rel_elements_dict(element)
5127
- data_dictionaries = related_elements.get("member_of_data_dicts_qnames", [])
5128
- data_structures = related_elements.get("data_structure_qnames", [])
5129
- assigned_meanings = related_elements.get("assigned_meanings_qnames", [])
5130
- parent_names = related_elements.get("parent_qnames", [])
5193
+ associated_elements = self.get_data_rel_elements_dict(element)
5194
+ data_specs = associated_elements.get("member_of_data_spec_qnames", [])
5195
+ # data_structures = associated_elements.get("member_of_data_struct_qnames", [])
5196
+ assigned_meanings = associated_elements.get("assigned_meanings_qnames", [])
5197
+ parent_names = associated_elements.get("parent_qnames", [])
5198
+ member_data_fields = associated_elements.get("member_data_field_qnames", [])
5199
+
5200
+ mermaid = element.get('mermaidGraph', "") or ""
5201
+ # mermaid_md = "```mermaid\n" + mermaid + "\n```"
5131
5202
 
5132
5203
  return {
5133
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'description': description,
5134
- 'qualified_name': qualified_name, 'namespace': namespace, 'version_identifier': version_id
5204
+ 'GUID': guid, 'display_name': display_name, 'qualified_name': qualified_name, 'description': description, 'data_fields': member_data_fields,
5205
+ 'data_specification': data_specs, 'namespace': namespace, 'version_identifier': version_id, 'properties': properties,
5206
+ 'extended_properties': extended_properties, 'additional_properties': additional_properties, 'mermaid': mermaid
5135
5207
  }
5136
5208
 
5137
5209
  def _extract_data_class_properties(self, element: dict) -> dict:
@@ -5150,9 +5222,37 @@ r replace_all_properties: bool, default = False
5150
5222
  description = properties.get("description", "") or ""
5151
5223
  qualified_name = properties.get("qualifiedName", "") or ""
5152
5224
 
5225
+ data_type = properties.get('dataType', "") or ""
5226
+ match_property_names = properties.get('matchPropertyNames', []) or []
5227
+ match_threshold = properties.get('matchThreshold', 0)
5228
+ allow_duplicate_values = properties.get('allowDuplicateValues', False)
5229
+ is_case_sensitive = properties.get('isCaseSensitive', False)
5230
+ is_nullable = properties.get('isNullable', False)
5231
+
5232
+ # Get data type from extendedProperties and additionalProperties if available
5233
+ extended_properties = properties.get("extendedProperties", {})
5234
+ additional_properties = properties.get("additionalProperties", {})
5235
+
5236
+ # Now lets get the related elements
5237
+ associated_elements = self.get_data_rel_elements_dict(element)
5238
+ data_dictionaries = associated_elements.get("member_of_data_dicts_qnames", [])
5239
+ assigned_meanings = associated_elements.get("assigned_meanings_qnames", [])
5240
+ parent_names = associated_elements.get("parent_qnames", [])
5241
+ nested_data_classes = associated_elements.get("nested_data_class_qnames", [])
5242
+ specialized_data_classes = associated_elements.get("specialized_data_class_qnames", [])
5243
+ mermaid = element.get('mermaidGraph', "") or ""
5244
+
5153
5245
  return {
5154
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'description': description,
5155
- 'qualified_name': qualified_name
5246
+ 'GUID': guid,'display_name': display_name, 'qualified_name': qualified_name,'description': description,
5247
+ 'assigned_meanings': assigned_meanings,
5248
+ 'data_type': data_type, 'match_property_names': match_property_names,
5249
+ 'match_threshold': match_threshold, 'allow_duplicate_values': allow_duplicate_values,
5250
+ 'is_case_sensitive': is_case_sensitive, 'is_nullable': is_nullable,
5251
+ 'properties': properties, 'parent_names': parent_names, 'nested_data_classes': nested_data_classes,
5252
+ 'specialized_data_classes': specialized_data_classes,
5253
+ 'extended_properties': extended_properties,
5254
+ 'additional_properties': additional_properties, 'data_dictionaries': data_dictionaries,
5255
+ 'mermaid': mermaid
5156
5256
  }
5157
5257
 
5158
5258
  def _extract_data_field_properties(self, element: dict) -> dict:
@@ -5179,25 +5279,26 @@ r replace_all_properties: bool, default = False
5179
5279
  ordered_values = properties.get('orderedValues', False)
5180
5280
  sort_order = properties.get('sortOrder', "") or ""
5181
5281
 
5182
-
5183
-
5184
5282
  # Get data type from extendedProperties and additionalProperties if available
5185
5283
  extended_properties = properties.get("extendedProperties", {})
5186
5284
  additional_properties = properties.get("additionalProperties", {})
5187
5285
 
5188
5286
  # Now lets get the related elements
5189
- related_elements = self.get_data_field_rel_elements_dict(element)
5190
- data_dictionaries = related_elements.get("member_of_data_dicts_qnames",[])
5191
- data_structures = related_elements.get("data_structure_qnames",[])
5192
- assigned_meanings = related_elements.get("assigned_meanings_qnames",[])
5193
- parent_names = related_elements.get("parent_qnames",[])
5287
+ associated_elements = self.get_data_rel_elements_dict(element)
5288
+ data_dictionaries = associated_elements.get("member_of_data_dicts_qnames",[])
5289
+ data_structures = associated_elements.get("data_structure_qnames",[])
5290
+ assigned_meanings = associated_elements.get("assigned_meanings_qnames",[])
5291
+ parent_names = associated_elements.get("parent_qnames",[])
5292
+ data_class = associated_elements.get("data_class_qnames",[])
5293
+ mermaid = element.get('mermaidGraph', "") or ""
5194
5294
 
5195
5295
  return {
5196
- 'display_name': display_name, 'description': description, 'assigned_meanings': assigned_meanings,
5197
- 'qualified_name': qualified_name, 'data_type': data_type, 'guid': guid, 'properties': properties,
5296
+ 'GUID': guid,'display_name': display_name, 'qualified_name': qualified_name,'description': description,
5297
+ 'assigned_meanings': assigned_meanings,
5298
+ 'data_type': data_type, 'data_class': data_class, 'properties': properties,
5198
5299
  'is_nullable': is_nullable, 'minimum_length': minimum_length, 'length': length, 'precision': precision,
5199
5300
  'ordered_values': ordered_values, 'sort_order': sort_order, 'parent_names': parent_names, 'extended_properties': extended_properties,
5200
- 'additional_properties': additional_properties,'data_dictionaries': data_dictionaries, 'data_structures': data_structures
5301
+ 'additional_properties': additional_properties,'data_dictionaries': data_dictionaries, 'data_structures': data_structures, 'mermaid': mermaid
5201
5302
  }
5202
5303
 
5203
5304
  def generate_basic_structured_output(self, elements, filter, output_format) -> str | list:
@@ -5243,10 +5344,10 @@ r replace_all_properties: bool, default = False
5243
5344
  Returns:
5244
5345
  Formatted output as string or list of dictionaries
5245
5346
  """
5246
- if output_format in ["MD", "FORM", "REPORT", "LIST"]:
5347
+ if output_format in ["MD", "FORM", "REPORT", "LIST", "MERMAID"]:
5247
5348
  # Define columns for LIST format
5248
5349
  columns = [{'name': 'Structure Name', 'key': 'display_name'},
5249
- {'name': 'Qualified Name', 'key': 'qualified_name'}, {'name': 'Namespace', 'key': 'namespace'},
5350
+ {'name': 'Qualified Name', 'key': 'qualified_name','format': True}, {'name': 'Namespace', 'key': 'namespace'},
5250
5351
  {'name': 'Version', 'key': 'version_identifier'},
5251
5352
  {'name': 'Description', 'key': 'description', 'format': True}]
5252
5353
 
@@ -5268,10 +5369,10 @@ r replace_all_properties: bool, default = False
5268
5369
  Returns:
5269
5370
  Formatted output as string or list of dictionaries
5270
5371
  """
5271
- if output_format in ["MD", "FORM", "REPORT", "LIST"]:
5372
+ if output_format in ["DICT", "MD", "FORM", "REPORT", "LIST", "MERMAID"]:
5272
5373
  # Define columns for LIST format
5273
5374
  columns = [{'name': 'Class Name', 'key': 'display_name'},
5274
- {'name': 'Qualified Name', 'key': 'qualified_name'},
5375
+ {'name': 'Qualified Name', 'key': 'qualified_name','format': True},
5275
5376
  {'name': 'Description', 'key': 'description', 'format': True}]
5276
5377
 
5277
5378
  return generate_output(elements=elements, search_string=filter, entity_type="Data Class",
@@ -5292,10 +5393,10 @@ r replace_all_properties: bool, default = False
5292
5393
  Returns:
5293
5394
  Formatted output as a string or list of dictionaries
5294
5395
  """
5295
- if output_format in ["MD", "FORM", "REPORT", "LIST", "DICT"]:
5396
+ if output_format in ["MD", "FORM", "REPORT", "LIST", "DICT", "MERMAID"]:
5296
5397
  # Define columns for LIST format
5297
5398
  columns = [{'name': 'Field Name', 'key': 'display_name'},
5298
- {'name': 'Qualified Name', 'key': 'qualified_name'}, {'name': 'Data Type', 'key': 'data_type'},
5399
+ {'name': 'Qualified Name', 'key': 'qualified_name','format': True}, {'name': 'Data Type', 'key': 'data_type'},
5299
5400
  {'name': 'Description', 'key': 'description', 'format': True}]
5300
5401
 
5301
5402
  return generate_output(elements=elements, search_string=filter, entity_type="Data Field",
@@ -90,7 +90,7 @@ class GlossaryBrowser(Client):
90
90
  category_qualified_names = cat_md_qn.rstrip(',')
91
91
 
92
92
  result = {
93
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'description': description,
93
+ 'GUID': guid, 'properties': properties, 'display_name': display_name, 'description': description,
94
94
  'language': language, 'usage': usage, 'qualified_name': qualified_name
95
95
  }
96
96
 
@@ -312,7 +312,7 @@ class GlossaryBrowser(Client):
312
312
  aliases = ", ".join(properties.get("aliases", "")) or ""
313
313
 
314
314
  return {
315
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'aliases': aliases,
315
+ 'GUID': guid, 'properties': properties, 'display_name': display_name, 'aliases': aliases,
316
316
  'summary': summary, 'description': description, 'examples': examples, 'usage': usage,
317
317
  'version identifier': pub_version, 'qualified_name': qualified_name, 'status': status
318
318
  }
@@ -626,7 +626,7 @@ class GlossaryBrowser(Client):
626
626
  qualified_name = properties.get("qualifiedName", "") or ""
627
627
 
628
628
  return {
629
- 'guid': guid, 'properties': properties, 'display_name': display_name, 'description': description,
629
+ 'GUID': guid, 'properties': properties, 'display_name': display_name, 'description': description,
630
630
  'qualified_name': qualified_name
631
631
  }
632
632
 
@@ -1051,7 +1051,6 @@ class GlossaryBrowser(Client):
1051
1051
  "class": "SearchStringRequestBody", "searchString": search_string, "effectiveTime": effective_time,
1052
1052
  "typeName": type_name,
1053
1053
  }
1054
- body = body_slimmer(body)
1055
1054
 
1056
1055
  url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/glossary-browser/glossaries/"
1057
1056
  f"by-search-string?startFrom={start_from}&pageSize={page_size}&startsWith={starts_with_s}&"
@@ -2176,11 +2175,11 @@ class GlossaryBrowser(Client):
2176
2175
  parent_guid = parent['elementHeader']['guid']
2177
2176
  parent_name = parent['glossaryCategoryProperties'].get('displayName', '---')
2178
2177
  parent_info = {
2179
- 'guid': parent_guid, 'name': parent_name
2178
+ 'GUID': parent_guid, 'name': parent_name
2180
2179
  }
2181
2180
 
2182
2181
  return {
2183
- 'guid': category_guid, 'name': display_name, 'qualifiedName': qualified_name,
2182
+ 'GUID': category_guid, 'name': display_name, 'qualifiedName': qualified_name,
2184
2183
  'description': description, 'parent': parent_info, 'children': children
2185
2184
  }
2186
2185
 
@@ -27,6 +27,7 @@ def make_preamble(obj_type: str, search_string: str, output_format: str = 'MD')
27
27
  depending on the output format.
28
28
  """
29
29
  # search_string = search_string if search_string else "All Elements"
30
+ elements_md = ""
30
31
  elements_action = "Update " + obj_type
31
32
  if output_format == "FORM":
32
33
  preamble = f"\n# Update {obj_type} Form - created at {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
@@ -34,7 +35,7 @@ def make_preamble(obj_type: str, search_string: str, output_format: str = 'MD')
34
35
  preamble += f"\t {obj_type} found from the search string: `{search_string}`\n\n"
35
36
  return preamble, elements_action
36
37
  elif output_format == "REPORT":
37
- elements_md = (f"# {obj_type} Report - created at {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
38
+ elements_md += (f"# {obj_type} Report - created at {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
38
39
  f"\t{obj_type} found from the search string: `{search_string}`\n\n")
39
40
  elements_action = None
40
41
  return elements_md, elements_action
@@ -56,17 +57,28 @@ def make_md_attribute(attribute_name: str, attribute_value: str, output_type: st
56
57
  output = ""
57
58
  if isinstance(attribute_value,str):
58
59
  attribute_value = attribute_value.strip() if attribute_value else ""
59
- attribute_title = attribute_name.title() if attribute_name else ""
60
+ elif isinstance(attribute_value,list):
61
+ attribute_value = ",\n".join(attribute_value)
62
+ if attribute_name:
63
+ if attribute_name.upper() == "GUID":
64
+ attribute_title = attribute_name.upper()
65
+ else:
66
+ attribute_title = attribute_name.title()
67
+ else:
68
+ attribute_title = ""
69
+
60
70
  if output_type in ["FORM", "MD"]:
71
+ if attribute_name.lower() == "mermaid":
72
+ return "\n"
61
73
  output = f"## {attribute_title}\n{attribute_value}\n\n"
62
74
  elif output_type == "REPORT":
63
- if attribute_title == 'Mermaid Graph':
75
+ if attribute_title in ['Mermaid Graph', 'Mermaid']:
64
76
  output = f"## Mermaid Graph\n```mermaid\n{attribute_value}\n```\n"
65
77
  elif attribute_value:
66
78
  output = f"## {attribute_title}\n{attribute_value}\n\n"
67
79
  return output
68
80
 
69
- def format_for_markdown_table(text: str) -> str:
81
+ def format_for_markdown_table(text: str, guid: str = None) -> str:
70
82
  """
71
83
  Format text for markdown tables by replacing newlines with spaces and escaping pipe characters.
72
84
  No truncation is applied to allow full-length text display regardless of console width.
@@ -80,9 +92,13 @@ def format_for_markdown_table(text: str) -> str:
80
92
  if not text:
81
93
  return ""
82
94
  # Replace newlines with spaces and escape pipe characters
83
- return text.replace("\n", " ").replace("|", "\\|")
95
+ t = text.replace("\n", " ").replace("|", "\\|")
96
+ if '::' in t and guid:
97
+ t = f" [{t}](#{guid}) "
98
+ return t
84
99
 
85
- def generate_entity_md(elements: List[Dict],
100
+
101
+ def generate_entity_md(elements: List[Dict],
86
102
  elements_action: str,
87
103
  output_format: str,
88
104
  entity_type: str,
@@ -112,28 +128,29 @@ def generate_entity_md(elements: List[Dict],
112
128
  # Get additional properties if function is provided
113
129
  additional_props = {}
114
130
  if get_additional_props_func:
115
- additional_props = get_additional_props_func(element, props['guid'], output_format)
131
+ additional_props = get_additional_props_func(element,props['GUID'], output_format)
132
+
116
133
 
117
134
  # Format header based on output format
118
135
  if output_format in ['FORM', 'MD']:
119
136
  elements_md += f"# {elements_action}\n\n"
120
137
  elements_md += f"## {entity_type} Name \n\n{props['display_name']}\n\n"
121
138
  elif output_format == 'REPORT':
122
- elements_md += f"# {entity_type} Name: {props['display_name']}\n\n"
139
+ elements_md += f'<a id="{props["GUID"]}"></a>\n\n# {entity_type} Name: {props["display_name"]}\n\n'
123
140
  else:
124
141
  elements_md += f"## {entity_type} Name \n\n{props['display_name']}\n\n"
125
142
 
126
143
  # Add common attributes
127
144
  for key, value in props.items():
128
- if key not in ['guid', 'properties', 'display_name']:
145
+ if key not in [ 'properties', 'display_name']:
129
146
  elements_md += make_md_attribute(key.replace('_', ' '), value, output_format)
130
147
 
131
148
  # Add additional properties
132
149
  for key, value in additional_props.items():
133
150
  elements_md += make_md_attribute(key.replace('_', ' '), value, output_format)
134
151
 
135
- # Add GUID
136
- elements_md += make_md_attribute("GUID", props['guid'], output_format)
152
+ # # Add GUID
153
+ # elements_md += make_md_attribute("GUID",props['GUID'], output_format)
137
154
 
138
155
  # Add separator if not the last element
139
156
  if element != elements[-1]:
@@ -186,7 +203,7 @@ def generate_entity_md_table(elements: List[Dict],
186
203
  # Get additional properties if function is provided
187
204
  additional_props = {}
188
205
  if get_additional_props_func:
189
- additional_props = get_additional_props_func(element, props['guid'], output_format)
206
+ additional_props = get_additional_props_func(element,props['GUID'], output_format)
190
207
 
191
208
  # Build row
192
209
  row = "| "
@@ -202,7 +219,7 @@ def generate_entity_md_table(elements: List[Dict],
202
219
 
203
220
  # Format the value if needed
204
221
  if 'format' in column and column['format']:
205
- value = format_for_markdown_table(value)
222
+ value = format_for_markdown_table(value, props['GUID'])
206
223
 
207
224
  row += f"{value} | "
208
225
 
@@ -240,7 +257,7 @@ def generate_entity_dict(elements: List[Dict],
240
257
  # Get additional properties if function is provided
241
258
  additional_props = {}
242
259
  if get_additional_props_func:
243
- additional_props = get_additional_props_func(element, props['guid'], output_format)
260
+ additional_props = get_additional_props_func(element,props['GUID'], output_format)
244
261
 
245
262
  # Create entity dictionary
246
263
  entity_dict = {}
@@ -308,6 +325,8 @@ def extract_basic_dict(elements: Union[Dict, List[Dict]]) -> Union[Dict, List[Di
308
325
 
309
326
  result = []
310
327
  for element in elements:
328
+ if element is None:
329
+ continue
311
330
  body = {'guid': element['elementHeader']['guid']}
312
331
  for key in element['properties']:
313
332
  body[key] = element['properties'][key]