pyegeria 5.4.3.2__py3-none-any.whl → 5.4.3.4__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 (53) hide show
  1. commands/cat/debug_log.2025-09-01_07-02-58_818650.log.zip +0 -0
  2. commands/cat/debug_log.2025-09-02_07-44-39_567276.log.zip +0 -0
  3. commands/cat/debug_log.2025-09-03_07-45-21_986388.log.zip +0 -0
  4. commands/cat/debug_log.log +5379 -8107
  5. commands/cat/list_format_set.py +2 -2
  6. commands/tech/list_information_supply_chains.py +1 -1
  7. commands/tech/list_solution_blueprints.py +1 -1
  8. commands/tech/list_solution_components.py +1 -1
  9. commands/tech/list_solution_roles.py +1 -1
  10. md_processing/__init__.py +0 -4
  11. md_processing/data/commands.json +1258 -615
  12. md_processing/dr_egeria.py +6 -9
  13. md_processing/dr_egeria_inbox/data_spec_test.md +44 -418
  14. md_processing/dr_egeria_inbox/gov_def.md +239 -3
  15. md_processing/dr_egeria_inbox/product.md +13 -5
  16. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +209 -0
  17. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +263 -0
  18. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +2374 -0
  19. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +2374 -0
  20. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +2321 -0
  21. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +2304 -0
  22. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +2324 -0
  23. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +2324 -0
  24. md_processing/md_commands/data_designer_commands.py +170 -570
  25. md_processing/md_commands/product_manager_commands.py +1 -1
  26. md_processing/md_processing_utils/common_md_utils.py +55 -13
  27. md_processing/md_processing_utils/extraction_utils.py +14 -7
  28. md_processing/md_processing_utils/md_processing_constants.py +1 -1
  29. pyegeria/___external_references.py +3255 -0
  30. pyegeria/__init__.py +1 -1
  31. pyegeria/_client_new.py +9 -7
  32. pyegeria/_output_formats.py +124 -3
  33. pyegeria/collection_manager.py +17 -56
  34. pyegeria/config.py +10 -1
  35. pyegeria/data_designer.py +172 -124
  36. pyegeria/egeria_client.py +1 -1
  37. pyegeria/egeria_tech_client.py +1 -1
  38. pyegeria/glossary_manager.py +71 -85
  39. pyegeria/governance_officer.py +26 -29
  40. pyegeria/output_formatter.py +127 -1
  41. pyegeria/project_manager.py +33 -36
  42. pyegeria/{solution_architect_omvs.py → solution_architect.py} +443 -388
  43. {pyegeria-5.4.3.2.dist-info → pyegeria-5.4.3.4.dist-info}/METADATA +1 -1
  44. {pyegeria-5.4.3.2.dist-info → pyegeria-5.4.3.4.dist-info}/RECORD +47 -41
  45. md_processing/dr_egeria_outbox/friday/processed-2025-08-29 16:30-output_tests.md +0 -103
  46. md_processing/dr_egeria_outbox/friday/processed-2025-08-29 16:40-output_tests.md +0 -115
  47. md_processing/dr_egeria_outbox/friday/processed-2025-08-30 21:15-glossary_test1.md +0 -326
  48. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 13:27-glossary_test1.md +0 -369
  49. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 13:33-glossary_test1.md +0 -392
  50. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 20:57-glossary_test1.md +0 -400
  51. {pyegeria-5.4.3.2.dist-info → pyegeria-5.4.3.4.dist-info}/LICENSE +0 -0
  52. {pyegeria-5.4.3.2.dist-info → pyegeria-5.4.3.4.dist-info}/WHEEL +0 -0
  53. {pyegeria-5.4.3.2.dist-info → pyegeria-5.4.3.4.dist-info}/entry_points.txt +0 -0
@@ -22,6 +22,7 @@ from pyegeria.output_formatter import (
22
22
  _extract_referenceable_properties,
23
23
  populate_columns_from_properties,
24
24
  get_required_relationships,
25
+ populate_common_columns,
25
26
  )
26
27
  from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
27
28
 
@@ -108,16 +109,26 @@ class GovernanceOfficer(Client2):
108
109
  output_format: str = 'DICT', output_format_set: dict | str = None
109
110
  ) -> str | list:
110
111
  """
111
- Generate output for governance definitions in the specified format, using output format sets.
112
+ Render governance definitions using the shared output pipeline.
112
113
 
113
- Args:
114
- elements: Dictionary or list of dictionaries containing governance definition elements
115
- search_string: The search string used to find the elements
116
- output_format: The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID, HTML)
117
- output_format_set: Optional format set name or structure to control columns
114
+ Parameters
115
+ ----------
116
+ elements : dict | list[dict]
117
+ Element(s) returned by the OMVS.
118
+ search_string : str
119
+ The search string used to retrieve these elements (shown in preamble for some formats).
120
+ element_type_name : str, optional
121
+ Friendly type label to display (defaults to "Governance Definition").
122
+ output_format : str
123
+ One of: MD, FORM, REPORT, LIST, DICT, MERMAID, HTML.
124
+ output_format_set : dict | str, optional
125
+ Either a label for a format set or a concrete format-set dict. When omitted, a sensible
126
+ default for Governance Definitions is chosen, falling back to "Default".
118
127
 
119
- Returns:
120
- Formatted output as string or list of dictionaries
128
+ Returns
129
+ -------
130
+ str | list
131
+ Rendered output in the requested format.
121
132
  """
122
133
  # Ensure elements handled consistently for MERMAID
123
134
  if output_format == "MERMAID":
@@ -167,27 +178,13 @@ class GovernanceOfficer(Client2):
167
178
  Returns:
168
179
  dict: columns_struct with populated 'value' fields
169
180
  """
170
- col_data = populate_columns_from_properties(element, columns_struct)
171
- columns_list = col_data.get('formats', {}).get('columns', [])
172
-
173
- # Header-derived values (GUID, type_name, etc.)
174
- header_props = _extract_referenceable_properties(element)
175
- for column in columns_list:
176
- key = column.get('key')
177
- if key in header_props:
178
- column['value'] = header_props.get(key)
179
- elif isinstance(key, str) and key.lower() == 'guid':
180
- column['value'] = header_props.get('GUID')
181
-
182
- # Populate requested relationship-based columns generically
183
- col_data = get_required_relationships(element, col_data)
184
-
185
- # Mermaid graph if requested
186
- for column in columns_list:
187
- if column.get('key') == 'mermaid':
188
- column['value'] = element.get('mermaidGraph', '') or ''
189
- break
190
-
181
+ # Use the common population pipeline to reduce duplication
182
+ col_data = populate_common_columns(element, columns_struct,
183
+ include_header=True,
184
+ include_relationships=True,
185
+ include_subject_area=True,
186
+ mermaid_source_key='mermaidGraph',
187
+ mermaid_dest_key='mermaid')
191
188
  return col_data
192
189
 
193
190
  def _extract_gov_def_list(self, element: Union[Dict, List[Dict]]) -> List[Dict]:
@@ -677,7 +677,7 @@ def generate_entity_dict(elements: List[Dict],
677
677
  value = format_for_markdown_table(value, guid or props.get('GUID'))
678
678
  entity_dict[name] = value
679
679
  else:
680
- props = extract_properties_func(element)
680
+ props = extract_properties_func(element, columns_struct)
681
681
  # Add properties based on include/exclude lists
682
682
  for key, value in props.items():
683
683
  if key not in ['properties', 'mermaid']: # Skip the raw properties object
@@ -721,6 +721,127 @@ def generate_entity_dict(elements: List[Dict],
721
721
 
722
722
  return result
723
723
 
724
+ def resolve_output_formats(entity_type: str,
725
+ output_format: str,
726
+ output_format_set: Optional[Union[str, dict]] = None,
727
+ default_label: Optional[str] = None) -> Optional[dict]:
728
+ """
729
+ Resolve an output format set structure given an entity type, the desired output format
730
+ (e.g., DICT, LIST, MD, REPORT, FORM), and either a label (str) or a dict of format sets.
731
+
732
+ Selection order:
733
+ - If output_format_set is a str: select by label.
734
+ - If output_format_set is a dict: use get_output_format_type_match to pick a matching format.
735
+ - Else: try selecting by entity_type or default_label.
736
+ - Fallback: select "Default".
737
+ """
738
+ from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
739
+
740
+ if isinstance(output_format_set, str):
741
+ return select_output_format_set(output_format_set, output_format)
742
+ if isinstance(output_format_set, dict):
743
+ return get_output_format_type_match(output_format_set, output_format)
744
+
745
+ label = default_label or entity_type
746
+ fmt = select_output_format_set(label, output_format)
747
+ if fmt is None:
748
+ fmt = select_output_format_set("Default", output_format)
749
+ return fmt
750
+
751
+
752
+ def overlay_additional_values(columns_struct: dict, extra: Optional[dict]) -> dict:
753
+ """
754
+ Overlay extra values into columns_struct only where the column's value is empty or missing.
755
+ Returns the modified columns_struct.
756
+ """
757
+ if not isinstance(columns_struct, dict) or not extra:
758
+ return columns_struct
759
+ columns = columns_struct.get('formats', {}).get('columns')
760
+ if not isinstance(columns, list):
761
+ return columns_struct
762
+ for col in columns:
763
+ if not isinstance(col, dict):
764
+ continue
765
+ key = col.get('key')
766
+ if not key:
767
+ continue
768
+ if col.get('value') in (None, "") and key in extra:
769
+ col['value'] = extra[key]
770
+ return columns_struct
771
+
772
+
773
+ def populate_common_columns(
774
+ element: dict,
775
+ columns_struct: dict,
776
+ *,
777
+ include_header: bool = True,
778
+ include_relationships: bool = True,
779
+ include_subject_area: bool = True,
780
+ mermaid_source_key: str = 'mermaidGraph',
781
+ mermaid_dest_key: str = 'mermaid'
782
+ ) -> dict:
783
+ """
784
+ Populate the common columns in columns_struct based on a standard Egeria element shape.
785
+
786
+ Steps:
787
+ - Populate from element.properties (camelCase mapped from snake_case keys)
788
+ - Optionally overlay header-derived values (GUID, type_name, times, etc.)
789
+ - Optionally populate relationship-based columns via get_required_relationships
790
+ - Optionally populate subject_area from element.elementHeader.subjectArea.classificationProperties.subjectAreaName
791
+ - If a column with key == mermaid_dest_key is present, set it from mermaid_source_key
792
+ - Do not overwrite non-empty values already set
793
+ """
794
+ # 1) Base properties
795
+ col_data = populate_columns_from_properties(element, columns_struct)
796
+ columns_list = col_data.get('formats', {}).get('columns', [])
797
+
798
+ # 2) Header overlay
799
+ header_props = _extract_referenceable_properties(element) if include_header else {}
800
+ guid = header_props.get('GUID') if include_header else None
801
+ if include_header:
802
+ for column in columns_list:
803
+ if not isinstance(column, dict):
804
+ continue
805
+ key = column.get('key')
806
+ if not key:
807
+ continue
808
+ if column.get('value') not in (None, ""):
809
+ continue
810
+ if key in header_props:
811
+ column['value'] = header_props.get(key)
812
+ elif isinstance(key, str) and key.lower() == 'guid':
813
+ column['value'] = guid
814
+
815
+ # 3) Relationships
816
+ if include_relationships:
817
+ col_data = get_required_relationships(element, col_data)
818
+
819
+ # 4) Subject area
820
+ if include_subject_area:
821
+ try:
822
+ subject_area = element.get('elementHeader', {}).get('subjectArea') or ""
823
+ subj_val = ""
824
+ if isinstance(subject_area, dict):
825
+ subj_val = subject_area.get('classificationProperties', {}).get('subjectAreaName', '')
826
+ for column in columns_list:
827
+ if column.get('key') == 'subject_area' and column.get('value') in (None, ""):
828
+ column['value'] = subj_val
829
+ except Exception as e:
830
+ logger.debug(f"populate_common_columns: subject_area handling error: {e}")
831
+
832
+ # 5) Mermaid
833
+ try:
834
+ mermaid_val = element.get(mermaid_source_key, '') or ''
835
+ for column in columns_list:
836
+ if column.get('key') == mermaid_dest_key and column.get('value') in (None, ""):
837
+ column['value'] = mermaid_val
838
+ break
839
+ except Exception as e:
840
+ logger.debug(f"populate_common_columns: mermaid handling error: {e}")
841
+
842
+ return col_data
843
+
844
+
724
845
  def extract_mermaid_only(elements: Union[Dict, List[Dict]]) -> Union[str, List[str]]:
725
846
  """
726
847
  Extract mermaid graph data from elements.
@@ -810,6 +931,11 @@ def generate_output(elements: Union[Dict, List[Dict]],
810
931
  Formatted output as string or list of dictionaries
811
932
  """
812
933
  columns = columns_struct['formats'].get('columns',None) if columns_struct else None
934
+ if not columns:
935
+ columns_struct = select_output_format_set("Default",output_format)
936
+ if columns_struct:
937
+ columns = columns_struct.get('formats', {}).get('columns', None)
938
+
813
939
  target_type = columns_struct.get('target_type', entity_type) if columns_struct else entity_type
814
940
  if target_type is None:
815
941
  target_type = entity_type
@@ -17,7 +17,7 @@ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequ
17
17
  TemplateRequestBody, DeleteRequestBody, UpdateElementRequestBody,
18
18
  NewRelationshipRequestBody)
19
19
  from pyegeria.output_formatter import generate_output, populate_columns_from_properties, \
20
- _extract_referenceable_properties, get_required_relationships
20
+ _extract_referenceable_properties, get_required_relationships, populate_common_columns, overlay_additional_values
21
21
  from pyegeria.utils import body_slimmer, dynamic_catch
22
22
 
23
23
  EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
@@ -28,20 +28,33 @@ PROJECT_TYPES = ["Project", "Campaign", "StudyProject", "Task", "PersonalProject
28
28
 
29
29
  class ProjectManager(Client2):
30
30
  """
31
- Create and manage projects. Projects may be organized in a hierarchy.
32
- See https://egeria-project.org/types/1/0130-Projects
33
-
34
- Attributes:
35
-
36
- server_name: str
37
- The name of the View Server to connect to.
38
- platform_url : str
39
- URL of the server platform to connect to
40
- user_id : str
41
- The identity of the user calling the method - this sets a default optionally used by the methods
42
- when the user doesn't pass the user_id on a method call.
43
- user_pwd: str
44
- The password associated with the user_id. Defaults to None
31
+ Manage Open Metadata Projects via the Project Manager OMVS.
32
+
33
+ This client provides asynchronous and synchronous helpers to create, update, search,
34
+ and relate Project elements and their subtypes (Campaign, StudyProject, Task, PersonalProject).
35
+
36
+ References
37
+ - Egeria concept: https://egeria-project.org/concepts/project
38
+ - Type lineage: https://egeria-project.org/types/1/0130-Projects
39
+
40
+ Parameters
41
+ -----------
42
+ view_server : str
43
+ The name of the View Server to connect to.
44
+ platform_url : str
45
+ URL of the server platform to connect to.
46
+ user_id : str
47
+ Default user identity for calls (can be overridden per call).
48
+ user_pwd : str, optional
49
+ Password for the user_id. If a token is supplied, this may be None.
50
+
51
+ Notes
52
+ -----
53
+ - Most high-level list/report methods accept an `output_format` and an optional `output_format_set` and
54
+ delegate rendering to `pyegeria.output_formatter.generate_output` along with shared helpers such as
55
+ `populate_common_columns`.
56
+ - Private extractor methods follow the convention: `_extract_<entity>_properties(element, columns_struct)` and
57
+ must return the same `columns_struct` with per-column `value` fields populated.
45
58
  """
46
59
 
47
60
  def __init__(
@@ -88,28 +101,12 @@ class ProjectManager(Client2):
88
101
  'properties': props,
89
102
  'elementHeader': element.get('elementHeader', {}),
90
103
  }
91
- col_data = populate_columns_from_properties(element, columns_struct)
92
- # col_data = populate_columns_from_properties(normalized, columns_struct)
104
+ # Common population pipeline
105
+ col_data = populate_common_columns(element, columns_struct)
93
106
  columns_list = col_data.get('formats', {}).get('columns', [])
94
- header_props = _extract_referenceable_properties(element)
95
- # Populate requested relationship-based columns generically
96
- col_data = get_required_relationships(element, col_data)
97
- additional_props = self._extract_additional_project_properties(element, columns_struct)
98
- guid = header_props.get('GUID')
99
-
100
- for column in columns_list:
101
- key = column.get('key')
102
- if key in header_props:
103
- column['value'] = header_props.get(key)
104
- elif key == 'project_roles':
105
- column['value'] = additional_props.get('project_roles', '')
106
- elif isinstance(key, str) and key.lower() == 'guid':
107
- column['value'] = guid
108
-
109
- for column in columns_list:
110
- if column.get('key') == 'mermaid' and not column.get('value'):
111
- column['value'] = element.get('mermaidGraph', '') or ''
112
- break
107
+ # Overlay extras (project roles) only where empty
108
+ extra = self._extract_additional_project_properties(element, columns_struct)
109
+ col_data = overlay_additional_values(col_data, extra)
113
110
  return col_data
114
111
 
115
112