pyegeria 5.4.0.dev2__py3-none-any.whl → 5.4.0.dev5__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.
- commands/cat/debug_log +227 -0
- commands/cat/dr_egeria_md.py +12 -3
- commands/cat/list_collections.py +7 -6
- commands/cat/list_data_designer.py +22 -10
- md_processing/__init__.py +4 -1
- md_processing/data/commands.json +142 -17
- md_processing/dr_egeria_outbox/processed-2025-06-22 21:06-dr_egeria_data_designer_1.md +134 -0
- md_processing/dr_egeria_outbox/processed-2025-06-22 21:13-dr_egeria_data_designer_1.md +133 -0
- md_processing/dr_egeria_outbox/processed-2025-06-22 21:19-dr_egeria_data_designer_1.md +141 -0
- md_processing/md_commands/data_designer_commands.py +408 -101
- md_processing/md_commands/glossary_commands.py +0 -30
- md_processing/md_commands/solution_architect_commands.py +1 -1
- md_processing/md_processing_utils/common_md_proc_utils.py +16 -4
- md_processing/md_processing_utils/md_processing_constants.py +3 -1
- pyegeria/collection_manager_omvs.py +120 -72
- pyegeria/data_designer_omvs.py +143 -42
- pyegeria/output_formatter.py +30 -11
- pyegeria/solution_architect_omvs.py +273 -5
- {pyegeria-5.4.0.dev2.dist-info → pyegeria-5.4.0.dev5.dist-info}/METADATA +1 -1
- {pyegeria-5.4.0.dev2.dist-info → pyegeria-5.4.0.dev5.dist-info}/RECORD +24 -24
- {pyegeria-5.4.0.dev2.dist-info → pyegeria-5.4.0.dev5.dist-info}/entry_points.txt +4 -3
- commands/cat/debug_log.2025-06-05_20-24-18_123924.log.zip +0 -0
- commands/cat/debug_log.2025-06-10_08-45-03_929921.log.zip +0 -0
- commands/cat/debug_log.2025-06-11_09-57-21_247890.log.zip +0 -0
- commands/cat/debug_log.2025-06-12_16-14-31_212042.log.zip +0 -0
- /commands/cat/{list_data_structures.py → list_data_structures_full.py} +0 -0
- {pyegeria-5.4.0.dev2.dist-info → pyegeria-5.4.0.dev5.dist-info}/LICENSE +0 -0
- {pyegeria-5.4.0.dev2.dist-info → pyegeria-5.4.0.dev5.dist-info}/WHEEL +0 -0
@@ -95,36 +95,6 @@ def update_term_categories(egeria_client: EgeriaTech, term_guid: str, categories
|
|
95
95
|
print_msg("DEBUG-INFO", msg, debug_level)
|
96
96
|
|
97
97
|
|
98
|
-
# def update_term_categories(egeria_client: EgeriaTech, term_guid: str, current_categories: List[str],
|
99
|
-
# new_categories: List[str]) -> None:
|
100
|
-
# """
|
101
|
-
# Updates the categories of a term.
|
102
|
-
#
|
103
|
-
# Args:
|
104
|
-
# egeria_client: The Egeria client to use for the update.
|
105
|
-
# term_guid: The GUID of the term to update.
|
106
|
-
# current_categories: The current categories of the term.
|
107
|
-
# new_categories: The new categories of the term.
|
108
|
-
# """
|
109
|
-
# if new_categories: # If categories are specified, add them
|
110
|
-
# for cat in new_categories:
|
111
|
-
# if cat not in current_categories:
|
112
|
-
# egeria_client.add_term_to_category(term_guid, cat)
|
113
|
-
# msg = f"Added term {term_guid} to category {cat}"
|
114
|
-
# print_msg("DEBUG-INFO", msg, debug_level)
|
115
|
-
# # Remove any categories that are not in the new list
|
116
|
-
# for cat in current_categories:
|
117
|
-
# if cat not in new_categories:
|
118
|
-
# egeria_client.remove_term_from_category(term_guid, cat)
|
119
|
-
# msg = f"Removed term {term_guid} from category {cat}"
|
120
|
-
# print_msg("DEBUG-INFO", msg, debug_level)
|
121
|
-
# else: # No categories specified - so remove any categories a term is in
|
122
|
-
# for cat in current_categories:
|
123
|
-
# egeria_client.remove_term_from_category(term_guid, cat)
|
124
|
-
# msg = f"Removed term {term_guid} from category {cat}"
|
125
|
-
# print_msg("DEBUG-INFO", msg, debug_level)
|
126
|
-
|
127
|
-
|
128
98
|
def process_glossary_upsert_command(egeria_client: EgeriaTech, txt: str, directive: str = "display") -> Optional[str]:
|
129
99
|
"""
|
130
100
|
Processes a glossary create or update object_action by extracting key attributes such as
|
@@ -917,7 +917,7 @@ def process_information_supply_chain_link_unlink_command(egeria_client: EgeriaTe
|
|
917
917
|
@logger.catch
|
918
918
|
def process_sol_arch_list_command(egeria_client: EgeriaTech, txt: str, kind:str, directive: str = "display" ) -> Optional[str]:
|
919
919
|
"""
|
920
|
-
Processes
|
920
|
+
Processes Solution Blueprint list object_action by extracting key attributes such as
|
921
921
|
search string from the given text.
|
922
922
|
|
923
923
|
:param txt: A string representing the input cell to be processed for
|
@@ -154,6 +154,9 @@ def parse_upsert_command(egeria_client: EgeriaTech, object_type: str, object_act
|
|
154
154
|
logger.error(msg)
|
155
155
|
parsed_output['valid'] = False
|
156
156
|
parsed_output['reason'] += msg
|
157
|
+
elif parsed_attributes[key]['valid'] is False:
|
158
|
+
parsed_output['valid'] = False
|
159
|
+
parsed_output['reason'] += parsed_attributes[key]['reason']
|
157
160
|
|
158
161
|
elif style == 'GUID':
|
159
162
|
parsed_attributes[key] = proc_simple_attribute(txt, object_action, labels, if_missing)
|
@@ -244,7 +247,7 @@ def parse_upsert_command(egeria_client: EgeriaTech, object_type: str, object_act
|
|
244
247
|
logger.info(msg)
|
245
248
|
|
246
249
|
|
247
|
-
if parsed_output.get('qualified_name',None):
|
250
|
+
if parsed_output.get('qualified_name',None) and "* Qualified Name" not in parsed_output['display']:
|
248
251
|
parsed_output['display'] += f"\n\t* Qualified Name: `{parsed_output['qualified_name']}`\n\t"
|
249
252
|
if parsed_output.get('guid',None):
|
250
253
|
parsed_output['display'] += f"\n\t* GUID: `{parsed_output['guid']}`\n\t"
|
@@ -341,8 +344,12 @@ def parse_view_command(egeria_client: EgeriaTech, object_type: str, object_actio
|
|
341
344
|
|
342
345
|
elif style == 'Reference Name':
|
343
346
|
parsed_attributes[key] = proc_ids(egeria_client, key, labels, txt, object_action, if_missing)
|
344
|
-
if ((if_missing == ERROR) and parsed_attributes[key].get("value", None)
|
345
|
-
'
|
347
|
+
if ((if_missing == ERROR) and parsed_attributes[key].get("value", None)):
|
348
|
+
msg = f"Required parameter `{parsed_attributes[key]['value']}` is missing"
|
349
|
+
logger.error(msg)
|
350
|
+
parsed_output['valid'] = False
|
351
|
+
parsed_output['reason'] += msg
|
352
|
+
elif parsed_attributes[key]['value'] and parsed_attributes['exists'] is False:
|
346
353
|
msg = f"Reference Name `{parsed_attributes[key]['value']}` is specified but does not exist"
|
347
354
|
logger.error(msg)
|
348
355
|
parsed_output['valid'] = False
|
@@ -366,7 +373,6 @@ def parse_view_command(egeria_client: EgeriaTech, object_type: str, object_actio
|
|
366
373
|
elif style == 'Bool':
|
367
374
|
parsed_attributes[key] = proc_bool_attribute(txt, object_action, labels, if_missing, default_value)
|
368
375
|
|
369
|
-
|
370
376
|
elif style == 'Reference Name List':
|
371
377
|
parsed_attributes[key] = proc_name_list(egeria_client, key, txt, labels, if_missing)
|
372
378
|
if (parsed_attributes[key].get("value", None) and (
|
@@ -671,6 +677,7 @@ def proc_ids(egeria_client: EgeriaTech, element_type: str, element_labels: set,
|
|
671
677
|
"""
|
672
678
|
Processes element identifiers from the input text using the labels supplied,
|
673
679
|
checking if the element exists in Egeria, and validating the information.
|
680
|
+
Only a single element is allowed.
|
674
681
|
|
675
682
|
Parameters
|
676
683
|
----------
|
@@ -704,7 +711,12 @@ def proc_ids(egeria_client: EgeriaTech, element_type: str, element_labels: set,
|
|
704
711
|
value = None
|
705
712
|
|
706
713
|
element_name = extract_attribute(txt, element_labels)
|
714
|
+
|
707
715
|
if element_name:
|
716
|
+
if '\n' in element_name or ',' in element_name:
|
717
|
+
msg = f"Element name `{element_name}` appears to be a list rather than a single element"
|
718
|
+
logger.error(msg)
|
719
|
+
return {"status": ERROR, "reason": msg, "value": None, "valid": False, "exists": False, }
|
708
720
|
q_name, guid, unique, exists = get_element_by_name(egeria_client, element_type, element_name)
|
709
721
|
value = element_name
|
710
722
|
else:
|
@@ -60,7 +60,9 @@ command_list = ["Provenance", "Create Glossary", "Update Glossary", "Create Term
|
|
60
60
|
"Update Term-Term Relationship", "Create Data Spec", "Create Data Specification", "Update Data Spec",
|
61
61
|
"Update Data Specification", "Create Data Field", "Update Data Field", "Create Data Structure",
|
62
62
|
"Update Data Structure", "Create Data Dictionary", "Update Data Dictionary", "Create Data Dict",
|
63
|
-
"Update Data Dict", " View Data Dictionary", "View Data Dictionaries", "
|
63
|
+
"Update Data Dict", " View Data Dictionary", "View Data Dictionaries", "View Data Specifications",
|
64
|
+
"View Data Specs", "View Data Structures", "View Data Structure", "View Data Fields", "View Data Field",
|
65
|
+
"View Dataa Classes", "View Data Class", "Create Data Class", "Update Data Class",]
|
64
66
|
|
65
67
|
|
66
68
|
pre_command = "\n---\n==> Processing object_action:"
|
@@ -303,7 +303,7 @@ class CollectionManager(Client):
|
|
303
303
|
return NO_ELEMENTS_FOUND
|
304
304
|
|
305
305
|
if output_format != 'JSON': # return a simplified markdown representation
|
306
|
-
return self.generate_collection_output(elements, None, None, output_format
|
306
|
+
return self.generate_collection_output(elements, None, None, output_format)
|
307
307
|
return elements
|
308
308
|
|
309
309
|
def find_collections(self, search_string: str, as_of_time: str = None, effective_time: str = None,
|
@@ -1138,6 +1138,7 @@ class CollectionManager(Client):
|
|
1138
1138
|
qualified_name = self.__create_qualified_name__("DataSpec", display_name)
|
1139
1139
|
|
1140
1140
|
body = body_slimmer({
|
1141
|
+
"class": "NewCollectionRequestBody",
|
1141
1142
|
"anchorGUID": anchor_guid, "anchorScopeGUID": anchor_scope_guid, "isOwnAnchor": is_own_anchor,
|
1142
1143
|
"parentGUID": parent_guid, "parentRelationshipTypeName": parent_relationship_type_name,
|
1143
1144
|
"parentAtEnd1": parent_at_end1, "collectionProperties": {
|
@@ -1276,6 +1277,7 @@ class CollectionManager(Client):
|
|
1276
1277
|
qualified_name = self.__create_qualified_name__("DataDict", display_name)
|
1277
1278
|
|
1278
1279
|
body = {
|
1280
|
+
"class": "NewCollectionRequestBody",
|
1279
1281
|
"anchorGUID": anchor_guid, "isOwnAnchor": is_own_anchor_s, "anchorScopeGUID": anchor_scope_guid,
|
1280
1282
|
"parentGUID": parent_guid, "parentRelationshipTypeName": parent_relationship_type_name,
|
1281
1283
|
"parentAtEnd1": parent_at_end1_s, "collectionProperties": {
|
@@ -2665,18 +2667,28 @@ class CollectionManager(Client):
|
|
2665
2667
|
display_name = properties.get("name", "") or ""
|
2666
2668
|
description = properties.get("description", "") or ""
|
2667
2669
|
qualified_name = properties.get("qualifiedName", "") or ""
|
2668
|
-
collection_type = properties.get("collectionType", "") or ""
|
2670
|
+
# collection_type = properties.get("collectionType", "") or ""
|
2669
2671
|
additional_properties = properties.get("additionalProperties", {}) or {}
|
2670
2672
|
extended_properties = properties.get("extendedProperties", {}) or {}
|
2671
|
-
classifications = ", ".join(properties.get("classifications", [])) or ""
|
2672
|
-
|
2673
|
-
|
2674
|
-
|
2675
|
-
|
2673
|
+
# classifications = ", ".join(properties.get("classifications", [])) or ""
|
2674
|
+
|
2675
|
+
classification_names = ""
|
2676
|
+
classifications = element['elementHeader'].get("classifications", [])
|
2677
|
+
for classification in classifications:
|
2678
|
+
classification_names += f"{classification['classificationName']}, "
|
2679
|
+
classification_names = classification_names[:-2]
|
2680
|
+
|
2681
|
+
member_names = ""
|
2682
|
+
members = self.get_member_list(collection_guid=guid)
|
2683
|
+
if isinstance(members, list):
|
2684
|
+
for member in members:
|
2685
|
+
member_names += f"{member['qualifiedName']}, "
|
2686
|
+
member_names = member_names[:-2]
|
2676
2687
|
|
2677
2688
|
return {
|
2678
|
-
|
2679
|
-
|
2689
|
+
'GUID': guid,'display_name': display_name,'qualified_name': qualified_name, 'description': description,
|
2690
|
+
'classifications': classification_names, 'members': member_names, 'properties': properties,
|
2691
|
+
# 'collection_type': collection_type,
|
2680
2692
|
'additional_properties': additional_properties, 'extended_properties': extended_properties,
|
2681
2693
|
}
|
2682
2694
|
|
@@ -2719,80 +2731,116 @@ class CollectionManager(Client):
|
|
2719
2731
|
# Default case
|
2720
2732
|
return None
|
2721
2733
|
|
2722
|
-
|
2723
|
-
|
2734
|
+
|
2735
|
+
def generate_collection_output(self, elements, filter, collection_type, output_format) -> str | list:
|
2724
2736
|
"""
|
2725
|
-
Generate output in the specified format
|
2737
|
+
Generate output for collections in the specified format.
|
2726
2738
|
|
2727
2739
|
Args:
|
2728
|
-
elements: Dictionary or list of dictionaries containing
|
2740
|
+
elements: Dictionary or list of dictionaries containing data field elements
|
2741
|
+
collection_type: str
|
2742
|
+
The type of collection.
|
2729
2743
|
filter: The search string used to find the elements
|
2730
|
-
output_format: The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID
|
2731
|
-
|
2732
|
-
The desired output profile - BASIC, CORE, FULL
|
2744
|
+
output_format: The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID)
|
2745
|
+
|
2733
2746
|
Returns:
|
2734
|
-
Formatted output as string or list of dictionaries
|
2747
|
+
Formatted output as a string or list of dictionaries
|
2735
2748
|
"""
|
2736
2749
|
if collection_type is None:
|
2737
2750
|
entity_type = "Collection"
|
2738
2751
|
else:
|
2739
2752
|
entity_type = collection_type
|
2740
2753
|
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2754
|
+
if output_format in ["MD", "FORM", "REPORT", "LIST", "DICT", "MERMAID"]:
|
2755
|
+
# Define columns for LIST format
|
2756
|
+
columns = [{'name': 'Name', 'key': 'display_name'},
|
2757
|
+
{'name': 'Qualified Name', 'key': 'qualified_name','format': True},
|
2758
|
+
{'name': 'Description', 'key': 'description', 'format': True},
|
2759
|
+
{'name': "Classifications", 'key': 'classifications' },
|
2760
|
+
{'name': 'Members', 'key': 'members', 'format': True},
|
2761
|
+
]
|
2762
|
+
|
2763
|
+
return generate_output(elements=elements, search_string=filter, entity_type=entity_type,
|
2764
|
+
output_format=output_format, extract_properties_func=self._extract_collection_properties,
|
2765
|
+
columns=columns if output_format == 'LIST' else None)
|
2766
|
+
else:
|
2767
|
+
return self.generate_basic_structured_output(elements, filter, output_format)
|
2768
|
+
|
2769
|
+
|
2770
|
+
# def generate_collection_output(self, elements, filter, collection_type: str, output_format,
|
2771
|
+
# output_profile: str = "CORE") -> str | list | dict:
|
2772
|
+
# """
|
2773
|
+
# Generate output in the specified format for the given elements.
|
2774
|
+
#
|
2775
|
+
# Args:
|
2776
|
+
# elements: Dictionary or list of dictionaries containing element data
|
2777
|
+
# filter: The search string used to find the elements
|
2778
|
+
# output_format: The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID, JSON)
|
2779
|
+
# output_profile: str, optional, default = "CORE"
|
2780
|
+
# The desired output profile - BASIC, CORE, FULL
|
2781
|
+
# Returns:
|
2782
|
+
# Formatted output as string or list of dictionaries
|
2783
|
+
# """
|
2784
|
+
# if collection_type is None:
|
2785
|
+
# entity_type = "Collection"
|
2786
|
+
# else:
|
2787
|
+
# entity_type = collection_type
|
2788
|
+
#
|
2789
|
+
# # For LIST and DICT formats, get member information
|
2790
|
+
#
|
2791
|
+
# if output_format in ["LIST", "DICT"]:
|
2792
|
+
# # Get the collection GUID
|
2793
|
+
# collection_guid = None
|
2794
|
+
# if isinstance(elements, dict):
|
2795
|
+
# collection_guid = elements.get('elementHeader', {}).get('guid')
|
2796
|
+
# elif isinstance(elements, list) and len(elements) > 0:
|
2797
|
+
# collection_guid = elements[0].get('elementHeader', {}).get('guid')
|
2798
|
+
#
|
2799
|
+
# # Get member list if we have a valid collection GUID
|
2800
|
+
# members = []
|
2801
|
+
# if collection_guid:
|
2802
|
+
# members = self.get_member_list(collection_guid=collection_guid)
|
2803
|
+
# if isinstance(members, str): # "No members found" case
|
2804
|
+
# members = []
|
2805
|
+
#
|
2806
|
+
# # For DICT format, include all member information in the result
|
2807
|
+
# if output_format == "DICT":
|
2808
|
+
# result = self.generate_basic_structured_output(elements, filter, output_format, collection_type)
|
2809
|
+
# if isinstance(result, list):
|
2810
|
+
# for item in result:
|
2811
|
+
# item['members'] = members
|
2812
|
+
# return result
|
2813
|
+
# elif isinstance(result, dict):
|
2814
|
+
# result['members'] = members
|
2815
|
+
# return result
|
2816
|
+
#
|
2817
|
+
# # For LIST format, add a column with bulleted list of qualified names
|
2818
|
+
# elif output_format == "LIST":
|
2819
|
+
# # Define columns for LIST format, including the new Members column
|
2820
|
+
# columns = [{'name': 'Collection Name', 'key': 'display_name'},
|
2821
|
+
# {'name': 'Qualified Name', 'key': 'qualified_name'},
|
2822
|
+
# {'name': 'Collection Type', 'key': 'collection_type'},
|
2823
|
+
# {'name': 'Description', 'key': 'description', 'format': True},
|
2824
|
+
# {'name': 'Classifications', 'key': 'classifications'},
|
2825
|
+
# {'name': 'Members', 'key': 'members', 'format': True}]
|
2826
|
+
#
|
2827
|
+
# # Create a function to add member information to the properties
|
2828
|
+
# def get_additional_props(element, guid, output_format):
|
2829
|
+
# if not members:
|
2830
|
+
# return {'members': ''}
|
2831
|
+
#
|
2832
|
+
# # Create a comma-separated list of qualified names (no newlines to avoid table formatting issues)
|
2833
|
+
# member_list = ", ".join([member.get('qualifiedName', '') for member in members])
|
2834
|
+
# return {'members': member_list}
|
2835
|
+
#
|
2836
|
+
# # Generate output with the additional properties
|
2837
|
+
#
|
2838
|
+
# return generate_output(elements=elements, search_string=filter, entity_type=entity_type,
|
2839
|
+
# output_format=output_format, extract_properties_func=self._extract_collection_properties,
|
2840
|
+
# get_additional_props_func=get_additional_props, columns=columns)
|
2841
|
+
#
|
2842
|
+
# # For FORM, REPORT, JSON formats, keep behavior unchanged
|
2843
|
+
# return self.generate_basic_structured_output(elements, filter, output_format, collection_type)
|
2796
2844
|
|
2797
2845
|
# def generate_data_class_output(self, elements, filter, output_format) -> str | list: # return
|
2798
2846
|
# self.generate_basic_structured_output(elements, filter, output_format) # # def generate_data_field_output(
|