pyegeria 5.4.3.3__py3-none-any.whl → 5.4.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 (230) hide show
  1. commands/cat/debug_log.2025-09-02_07-44-39_567276.log.zip +0 -0
  2. commands/cat/debug_log.2025-09-03_07-45-21_986388.log.zip +0 -0
  3. commands/cat/debug_log.2025-09-04_08-21-58_788009.log.zip +0 -0
  4. commands/cat/debug_log.2025-09-05_09-37-53_062579.log.zip +0 -0
  5. commands/cat/list_format_set.py +5 -3
  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 +9 -5
  11. md_processing/data/commands.json +7182 -1401
  12. md_processing/data/generated_format_sets.json +4137 -0
  13. md_processing/data/generated_format_sets.py +51 -0
  14. md_processing/dr_egeria.py +20 -11
  15. md_processing/md_commands/data_designer_commands.py +90 -425
  16. md_processing/md_commands/ext_ref_commands.py +543 -0
  17. md_processing/md_commands/old_solution_architect_commands.py +1139 -0
  18. md_processing/md_commands/solution_architect_commands.py +26 -59
  19. md_processing/md_processing_utils/common_md_utils.py +50 -1
  20. md_processing/md_processing_utils/debug_log +1 -3
  21. md_processing/md_processing_utils/dr-egeria-help-2025-09-09T11:10:03.md +3305 -0
  22. md_processing/md_processing_utils/extraction_utils.py +14 -7
  23. md_processing/md_processing_utils/gen_format_sets.py +422 -0
  24. md_processing/md_processing_utils/md_processing_constants.py +20 -2
  25. pyegeria/__init__.py +1 -1
  26. pyegeria/_client_new.py +9 -7
  27. pyegeria/_output_formats.py +278 -3
  28. pyegeria/collection_manager.py +20 -59
  29. pyegeria/config.py +10 -1
  30. pyegeria/data_designer.py +166 -117
  31. pyegeria/egeria_client.py +1 -1
  32. pyegeria/egeria_tech_client.py +4 -1
  33. pyegeria/external_references.py +1794 -0
  34. pyegeria/glossary_manager.py +71 -85
  35. pyegeria/governance_officer.py +26 -29
  36. pyegeria/output_formatter.py +127 -1
  37. pyegeria/project_manager.py +33 -36
  38. pyegeria/{solution_architect_omvs.py → solution_architect.py} +733 -873
  39. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/METADATA +1 -1
  40. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/RECORD +43 -219
  41. commands/.DS_Store +0 -0
  42. commands/cat/.DS_Store +0 -0
  43. commands/cat/.env +0 -8
  44. commands/cat/debug_log.2025-08-29_07-07-27_848189.log.zip +0 -0
  45. commands/cat/debug_log.2025-08-30_21-15-48_528443.log.zip +0 -0
  46. commands/cat/debug_log.log +0 -6102
  47. commands/cat/logs/pyegeria.log +0 -90
  48. commands/cli/debug_log.log +0 -0
  49. commands/doc/.DS_Store +0 -0
  50. commands/ops/logs/pyegeria.log +0 -0
  51. md_processing/.DS_Store +0 -0
  52. md_processing/.idea/.gitignore +0 -8
  53. md_processing/.idea/inspectionProfiles/Project_Default.xml +0 -59
  54. md_processing/.idea/md_processing.iml +0 -15
  55. md_processing/.idea/modules.xml +0 -8
  56. md_processing/.idea/sonarlint/issuestore/index.pb +0 -0
  57. md_processing/.idea/sonarlint/securityhotspotstore/index.pb +0 -0
  58. md_processing/.idea/vcs.xml +0 -6
  59. md_processing/.idea/workspace.xml +0 -107
  60. md_processing/dr_egeria_inbox/Derive-Dr-Gov-Defs.md +0 -8
  61. md_processing/dr_egeria_inbox/Dr.Egeria Templates.md +0 -873
  62. md_processing/dr_egeria_inbox/arch_test.md +0 -57
  63. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  64. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  65. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  66. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  67. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  68. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  69. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  70. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  71. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  72. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  73. md_processing/dr_egeria_inbox/collections.md +0 -39
  74. md_processing/dr_egeria_inbox/data_designer_debug.log +0 -6
  75. md_processing/dr_egeria_inbox/data_designer_out.md +0 -60
  76. md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
  77. md_processing/dr_egeria_inbox/data_field.md +0 -54
  78. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  79. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2340
  80. md_processing/dr_egeria_inbox/data_test.md +0 -179
  81. md_processing/dr_egeria_inbox/data_test2.md +0 -429
  82. md_processing/dr_egeria_inbox/data_test3.md +0 -462
  83. md_processing/dr_egeria_inbox/dr_egeria_data_designer_1.md +0 -124
  84. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  85. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  86. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -318
  87. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  88. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  89. md_processing/dr_egeria_inbox/generated_help_report.md +0 -9
  90. md_processing/dr_egeria_inbox/generated_help_terms.md +0 -842
  91. md_processing/dr_egeria_inbox/glossary_list.md +0 -5
  92. md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
  93. md_processing/dr_egeria_inbox/glossary_test1.md +0 -378
  94. md_processing/dr_egeria_inbox/gov_def.md +0 -718
  95. md_processing/dr_egeria_inbox/gov_def2.md +0 -447
  96. md_processing/dr_egeria_inbox/img.png +0 -0
  97. md_processing/dr_egeria_inbox/output_tests.md +0 -114
  98. md_processing/dr_egeria_inbox/product.md +0 -211
  99. md_processing/dr_egeria_inbox/rel.md +0 -8
  100. md_processing/dr_egeria_inbox/sb.md +0 -119
  101. md_processing/dr_egeria_inbox/solution-components.md +0 -136
  102. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  103. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  104. md_processing/dr_egeria_inbox/t2.md +0 -268
  105. md_processing/dr_egeria_outbox/.DS_Store +0 -0
  106. md_processing/dr_egeria_outbox/.obsidian/app.json +0 -1
  107. md_processing/dr_egeria_outbox/.obsidian/appearance.json +0 -1
  108. md_processing/dr_egeria_outbox/.obsidian/community-plugins.json +0 -7
  109. md_processing/dr_egeria_outbox/.obsidian/core-plugins.json +0 -33
  110. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/main.js +0 -5164
  111. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/manifest.json +0 -10
  112. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/styles.css +0 -624
  113. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/data.json +0 -10
  114. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/main.js +0 -4459
  115. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/manifest.json +0 -10
  116. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/data.json +0 -3
  117. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/main.js +0 -153
  118. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/manifest.json +0 -11
  119. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/styles.css +0 -1
  120. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/main.js +0 -500
  121. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +0 -12
  122. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/styles.css +0 -1
  123. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/data.json +0 -38
  124. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/main.js +0 -37
  125. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/manifest.json +0 -11
  126. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/styles.css +0 -220
  127. md_processing/dr_egeria_outbox/.obsidian/types.json +0 -28
  128. md_processing/dr_egeria_outbox/.obsidian/workspace.json +0 -270
  129. md_processing/dr_egeria_outbox/Button Test.md +0 -11
  130. md_processing/dr_egeria_outbox/Scripts/.DS_Store +0 -0
  131. md_processing/dr_egeria_outbox/Scripts/sendRest.js +0 -24
  132. md_processing/dr_egeria_outbox/Templates/sendToApi.md.md +0 -17
  133. md_processing/dr_egeria_outbox/Untitled.canvas +0 -1
  134. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 09:26-product.md +0 -210
  135. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +0 -209
  136. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +0 -263
  137. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +0 -2374
  138. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +0 -2374
  139. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +0 -2321
  140. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +0 -2304
  141. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +0 -2324
  142. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +0 -2324
  143. md_processing/dr_egeria_outbox/processed-2025-08-30 16:56-generated_help_terms.md +0 -795
  144. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +0 -719
  145. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +0 -41
  146. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +0 -33
  147. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +0 -192
  148. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:08-gov_def2.md +0 -486
  149. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:10-gov_def2.md +0 -486
  150. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:53-gov_def2.md +0 -486
  151. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:54-gov_def2.md +0 -486
  152. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:03-gov_def2.md +0 -486
  153. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:06-gov_def2.md +0 -486
  154. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:10-gov_def2.md +0 -486
  155. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:07-gov_def.md +0 -492
  156. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:25-gov_def.md +0 -520
  157. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:43-gov_def.md +0 -636
  158. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:46-gov_def.md +0 -636
  159. md_processing/family_docs/Data Designer/Create_Data_Class.md +0 -164
  160. md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +0 -30
  161. md_processing/family_docs/Data Designer/Create_Data_Field.md +0 -162
  162. md_processing/family_docs/Data Designer/Create_Data_Specification.md +0 -36
  163. md_processing/family_docs/Data Designer/Create_Data_Structure.md +0 -38
  164. md_processing/family_docs/Data Designer/View_Data_Classes.md +0 -78
  165. md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +0 -78
  166. md_processing/family_docs/Data Designer/View_Data_Fields.md +0 -78
  167. md_processing/family_docs/Data Designer/View_Data_Specifications.md +0 -78
  168. md_processing/family_docs/Data Designer/View_Data_Structures.md +0 -78
  169. md_processing/family_docs/Data Designer.md +0 -842
  170. md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +0 -42
  171. md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +0 -36
  172. md_processing/family_docs/Digital Product Manager/Create_Agreement.md +0 -96
  173. md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +0 -72
  174. md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +0 -102
  175. md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +0 -134
  176. md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +0 -60
  177. md_processing/family_docs/Digital Product Manager/Link_Contracts.md +0 -26
  178. md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +0 -30
  179. md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +0 -48
  180. md_processing/family_docs/Digital Product Manager.md +0 -668
  181. md_processing/family_docs/Glossary/Attach_Category_Parent.md +0 -18
  182. md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +0 -26
  183. md_processing/family_docs/Glossary/Create_Category.md +0 -38
  184. md_processing/family_docs/Glossary/Create_Glossary.md +0 -42
  185. md_processing/family_docs/Glossary/Create_Term.md +0 -70
  186. md_processing/family_docs/Glossary.md +0 -206
  187. md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +0 -106
  188. md_processing/family_docs/Governance Officer/Create_Certification_Type.md +0 -112
  189. md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +0 -114
  190. md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +0 -114
  191. md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +0 -114
  192. md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +0 -128
  193. md_processing/family_docs/Governance Officer/Create_Governance_Process.md +0 -122
  194. md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +0 -106
  195. md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +0 -122
  196. md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +0 -122
  197. md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +0 -106
  198. md_processing/family_docs/Governance Officer/Create_License_Type.md +0 -112
  199. md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +0 -122
  200. md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +0 -106
  201. md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +0 -118
  202. md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +0 -114
  203. md_processing/family_docs/Governance Officer/Create_Security_Group.md +0 -120
  204. md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +0 -122
  205. md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +0 -106
  206. md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +0 -32
  207. md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +0 -32
  208. md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +0 -32
  209. md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +0 -82
  210. md_processing/family_docs/Governance Officer.md +0 -2412
  211. md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +0 -70
  212. md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +0 -44
  213. md_processing/family_docs/Solution Architect/Create_Solution_Component.md +0 -96
  214. md_processing/family_docs/Solution Architect/Create_Solution_Role.md +0 -66
  215. md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +0 -32
  216. md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +0 -32
  217. md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +0 -32
  218. md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +0 -32
  219. md_processing/family_docs/Solution Architect/View_Solution_Components.md +0 -32
  220. md_processing/family_docs/Solution Architect/View_Solution_Roles.md +0 -32
  221. md_processing/family_docs/Solution Architect.md +0 -490
  222. md_processing/md_commands/old_project_commands.py +0 -164
  223. md_processing/md_processing_utils/debug_log.log +0 -5580
  224. md_processing/md_processing_utils/generated_help_terms.md +0 -842
  225. md_processing/md_processing_utils/logs/pyegeria.log +0 -56
  226. pyegeria/.DS_Store +0 -0
  227. pyegeria/___external_references.py +0 -3267
  228. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/LICENSE +0 -0
  229. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/WHEEL +0 -0
  230. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/entry_points.txt +0 -0
pyegeria/config.py CHANGED
@@ -25,6 +25,7 @@ import inspect
25
25
  import os
26
26
  import json
27
27
  from typing import List, Optional, Union, Dict, Any
28
+ import sys
28
29
 
29
30
  from loguru import logger
30
31
  from pydantic import BaseModel, Field, validator, ConfigDict
@@ -36,6 +37,12 @@ logger.disable("pyegeria")
36
37
  # --- Pydantic Settings for Environment Variables ---
37
38
 
38
39
  class PyegeriaSettings(BaseSettings):
40
+ """Top-level environment settings for pyegeria.
41
+
42
+ This class centralizes discovery of important filesystem paths and default
43
+ configuration values. It can be constructed directly or via `with_env_file`
44
+ to load overrides from a specific .env-like file.
45
+ """
39
46
  """
40
47
  Settings loaded from environment variables using pydantic-settings.
41
48
  This class is used to load environment variables from the .env file.
@@ -89,6 +96,7 @@ class PyegeriaSettings(BaseSettings):
89
96
  # --- Pydantic Models for Configuration ---
90
97
 
91
98
  class EnvironmentConfig(BaseModel):
99
+ """Runtime environment parameters that influence formatting and behavior."""
92
100
  """Environment configuration settings"""
93
101
  console_width: int = Field(default=200, alias="Console Width")
94
102
  dr_egeria_inbox: str = Field(default="md_processing/dr-egeria-inbox", alias="Dr.Egeria Inbox")
@@ -149,6 +157,7 @@ class UserProfileConfig(BaseModel):
149
157
 
150
158
 
151
159
  class AppConfig(BaseModel):
160
+ """Aggregated application configuration used by pyegeria components."""
152
161
  """Main application configuration"""
153
162
  Environment: EnvironmentConfig
154
163
  Debug: DebugConfig
@@ -333,7 +342,7 @@ def load_app_config(env_file: str | None = None):
333
342
  )
334
343
  log["logging_file_format"] = os.getenv(
335
344
  "PYEGERIA_LOGGING_FILE_FORMAT",
336
- log.get("logging_file_format", " {time:YYYY-MM-DD HH:mm:ss} | {level} | {function}:{line} - {message }-{extra}"),
345
+ log.get("logging_file_format", " {time:YYYY-MM-DD HH:mm:ss} | {level} | {function}:{line} - {message}-{extra}"),
337
346
  )
338
347
 
339
348
  # User Profile
pyegeria/data_designer.py CHANGED
@@ -18,7 +18,8 @@ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequ
18
18
  TemplateRequestBody,
19
19
  UpdateElementRequestBody, NewRelationshipRequestBody,
20
20
  DeleteRequestBody)
21
- from pyegeria.output_formatter import (extract_mermaid_only, extract_basic_dict)
21
+ from pyegeria.output_formatter import (extract_mermaid_only, extract_basic_dict, populate_columns_from_properties,
22
+ get_required_relationships, populate_common_columns)
22
23
  from pyegeria.output_formatter import (generate_output,
23
24
  _extract_referenceable_properties)
24
25
  from pyegeria.utils import body_slimmer, dynamic_catch
@@ -1296,11 +1297,10 @@ class DataDesigner(Client2):
1296
1297
 
1297
1298
  member_of_collections = el_struct.get("memberOfCollections", {})
1298
1299
  for collection in member_of_collections:
1299
- c_type = collection["relatedElement"]["properties"].get("collectionType", "") or ""
1300
+ type_name = collection["relatedElement"]["elementHeader"]["type"].get("typeName", "") or ""
1300
1301
  guid = collection["relatedElement"]["elementHeader"]["guid"]
1301
- name = collection["relatedElement"]["properties"].get("name", "") or ""
1302
+ name = collection["relatedElement"]["properties"].get("displayName", "") or ""
1302
1303
  qualifiedName = collection['relatedElement']["properties"].get("qualifiedName", "") or ""
1303
- type_name = collection["relatedElement"]["elementHeader"].get("classificationProperties",{}).get('anchorTypeName', None)
1304
1304
  if type_name:
1305
1305
  if type_name == "DataDictionary":
1306
1306
  member_of_data_dicts_guids.append(guid)
@@ -2516,7 +2516,7 @@ class DataDesigner(Client2):
2516
2516
 
2517
2517
  loop = asyncio.get_event_loop()
2518
2518
  response = loop.run_until_complete(
2519
- self._async_get_data_fields_by_name(filter, classification_names, body, start_from, page_size,
2519
+ self._async_get_data_fields_by_name(filter_string, classification_names, body, start_from, page_size,
2520
2520
  output_format, output_format_set))
2521
2521
  return response
2522
2522
 
@@ -4681,118 +4681,161 @@ class DataDesigner(Client2):
4681
4681
 
4682
4682
 
4683
4683
 
4684
- def _extract_data_structure_properties(self, element: dict) -> dict:
4685
- """
4686
- Extract common properties from a data structure element.
4687
-
4688
- Args:
4689
- element (dict): The data structure element
4690
-
4691
- Returns:
4692
- dict: Dictionary of extracted properties
4693
- """
4694
- props = _extract_referenceable_properties(element)
4695
-
4696
- props['properties'] = element.get('properties', {})
4697
-
4698
- props['namespace'] = props['properties'].get("namespace", "") or ""
4699
-
4700
- classification_names = []
4701
- for c in props['classifications']:
4702
- classification_names.append(c.get("classificationName", None))
4703
- props['classifications'] = classification_names
4704
-
4705
- # Now lets get the related elements
4706
- associated_elements = self.get_data_rel_elements_dict(element)
4707
- props['data_specs'] = associated_elements.get("member_of_data_spec_qnames", [])
4708
-
4709
- # data_structures = associated_elements.get("member_of_data_struct_qnames", [])
4710
- props['assigned_meanings'] = associated_elements.get("assigned_meanings_qnames", [])
4711
- props['parent_names'] = associated_elements.get("parent_qnames", [])
4712
- props['member_data_fields'] = associated_elements.get("member_data_field_qnames", [])
4713
-
4714
- props['mermaid'] = element.get('mermaidGraph', "") or ""
4715
-
4716
- return props
4717
-
4718
- def _extract_data_class_properties(self, element: dict) -> dict:
4719
- """
4720
- Extract common properties from a data class element.
4721
-
4722
- Args:
4723
- element (dict): The data class element
4724
-
4725
- Returns:
4726
- dict: Dictionary of extracted properties
4727
- """
4728
- props = _extract_referenceable_properties(element)
4729
- properties = element.get('properties', {})
4730
- props['properties'] = properties
4731
-
4732
- classification_names = []
4733
- for c in props['classifications']:
4734
- classification_names.append(c.get("classificationName", None))
4735
- props['classifications'] = classification_names
4736
-
4737
- props['namespace'] = props['properties'].get("namespace", "") or ""
4738
-
4739
- props['data_type'] = properties.get('dataType', "") or ""
4740
- props['match_property_names'] = properties.get('matchPropertyNames', []) or []
4741
- props['match_threshold'] = properties.get('matchThreshold', 0)
4742
- props['allow_duplicate_values'] = properties.get('allowDuplicateValues', False)
4743
- props['is_case_sensitive'] = properties.get('isCaseSensitive', False)
4744
- props['is_nullable'] = properties.get('isNullable', False)
4745
-
4746
- # Now lets get the related elements
4747
- associated_elements = self.get_data_rel_elements_dict(element)
4748
- props['data_dictionaries'] = associated_elements.get("member_of_data_dicts_qnames", [])
4749
- props['assigned_meanings'] = associated_elements.get("assigned_meanings_qnames", [])
4750
- props['parent_names'] = associated_elements.get("parent_qnames", [])
4751
- props['nested_data_classes'] = associated_elements.get("nested_data_class_qnames", [])
4752
- props['specialized_data_classes'] = associated_elements.get("specialized_data_class_qnames", [])
4753
- props['mermaid'] = element.get('mermaidGraph', "") or ""
4754
-
4755
- return props
4756
-
4757
- def _extract_data_field_properties(self, element: dict) -> dict:
4758
- """
4759
- Extract common properties from a data field element.
4760
-
4761
- Args:
4762
- element (dict): The data field element
4763
-
4764
- Returns:
4765
- dict: Dictionary of extracted properties
4766
- """
4767
- props = _extract_referenceable_properties(element)
4768
-
4769
- props['properties'] = element.get('properties', {})
4770
- props['namespace'] = props['properties'].get("namespace", "") or ""
4771
- properties = element.get('properties', {})
4772
-
4773
- classification_names = []
4774
- for c in props['classifications']:
4775
- classification_names.append(c.get("classificationName", None))
4776
- props['classifications'] = classification_names
4777
-
4778
- props['is_nullable'] = properties.get('isNullable', False)
4779
- props['data_type'] = properties.get('dataType', "") or ""
4780
- props['minimum_length'] = properties.get('minimumLength', 0)
4781
- props['length'] = properties.get('length', 0)
4782
- props['precision'] = properties.get('precision', 0)
4783
- props['ordered_values'] = properties.get('orderedValues', False)
4784
- props['sort_order'] = properties.get('sortOrder', "") or ""
4785
-
4786
- # Now lets get the related elements
4787
- associated_elements = self.get_data_rel_elements_dict(element)
4788
- props['data_dictionaries'] = associated_elements.get("member_of_data_dicts_qnames", [])
4789
- props['data_structures'] = associated_elements.get("data_structure_qnames", [])
4790
- props['assigned_meanings'] = associated_elements.get("assigned_meanings_qnames", [])
4791
- props['parent_names'] = associated_elements.get("parent_qnames", [])
4792
- props['data_class'] = associated_elements.get("data_class_qnames", [])
4793
- props['mermaid'] = element.get('mermaidGraph', "") or ""
4794
-
4795
- return props
4684
+ def _extract_data_structure_properties(self, element: dict, columns_struct: dict) -> dict:
4685
+ """Extractor for Data Structure elements with related overlay.
4686
+
4687
+ Pattern:
4688
+ - Populate common columns via populate_common_columns.
4689
+ - Derive related properties using get_data_rel_elements_dict from the element body.
4690
+ - Overlay values into matching columns' 'value' fields, handling formats as list or dict.
4691
+ - Return the enriched columns_struct.
4692
+ """
4693
+ col_data = populate_common_columns(element, columns_struct)
4694
+
4695
+ try:
4696
+ related_map = self.get_data_rel_elements_dict(element)
4697
+ except Exception:
4698
+ related_map = {}
4699
+
4700
+ if isinstance(related_map, dict) and related_map:
4701
+ try:
4702
+ formats = col_data.get("formats") if isinstance(col_data, dict) else None
4703
+ if isinstance(formats, list):
4704
+ targets = formats
4705
+ elif isinstance(formats, dict):
4706
+ inner = formats.get("formats") if isinstance(formats.get("formats"), (dict, list)) else None
4707
+ if isinstance(inner, list):
4708
+ targets = inner
4709
+ elif isinstance(inner, dict):
4710
+ targets = [inner]
4711
+ else:
4712
+ targets = [formats]
4713
+ else:
4714
+ targets = []
4715
+
4716
+ if targets:
4717
+ for fmt in targets:
4718
+ cols = fmt.get("columns", []) if isinstance(fmt, dict) else []
4719
+ for col in cols:
4720
+ key = col.get("key") if isinstance(col, dict) else None
4721
+ if key and key in related_map:
4722
+ col["value"] = related_map.get(key)
4723
+ else:
4724
+ cols = col_data.get("columns", []) if isinstance(col_data, dict) else []
4725
+ for col in cols:
4726
+ key = col.get("key") if isinstance(col, dict) else None
4727
+ if key and key in related_map:
4728
+ col["value"] = related_map.get(key)
4729
+ except Exception:
4730
+ pass
4731
+
4732
+ return col_data
4733
+
4734
+
4735
+ def _extract_data_class_properties(self, element: dict,columns_struct: dict) -> dict:
4736
+ """Extractor for Data Class elements with related overlay, mirroring Data Field pattern."""
4737
+ col_data = populate_common_columns(element, columns_struct)
4738
+
4739
+ try:
4740
+ related_map = self.get_data_rel_elements_dict(element)
4741
+ except Exception:
4742
+ related_map = {}
4743
+
4744
+ if isinstance(related_map, dict) and related_map:
4745
+ try:
4746
+ formats = col_data.get("formats") if isinstance(col_data, dict) else None
4747
+ if isinstance(formats, list):
4748
+ targets = formats
4749
+ elif isinstance(formats, dict):
4750
+ inner = formats.get("formats") if isinstance(formats.get("formats"), (dict, list)) else None
4751
+ if isinstance(inner, list):
4752
+ targets = inner
4753
+ elif isinstance(inner, dict):
4754
+ targets = [inner]
4755
+ else:
4756
+ targets = [formats]
4757
+ else:
4758
+ targets = []
4759
+
4760
+ if targets:
4761
+ for fmt in targets:
4762
+ cols = fmt.get("columns", []) if isinstance(fmt, dict) else []
4763
+ for col in cols:
4764
+ key = col.get("key") if isinstance(col, dict) else None
4765
+ if key and key in related_map:
4766
+ col["value"] = related_map.get(key)
4767
+ else:
4768
+ cols = col_data.get("columns", []) if isinstance(col_data, dict) else []
4769
+ for col in cols:
4770
+ key = col.get("key") if isinstance(col, dict) else None
4771
+ if key and key in related_map:
4772
+ col["value"] = related_map.get(key)
4773
+ except Exception:
4774
+ pass
4775
+
4776
+ return col_data
4777
+
4778
+ def _extract_data_field_properties(self, element: dict, columns_struct: dict) -> dict:
4779
+ """Extractor for Data Field elements.
4780
+
4781
+ Steps:
4782
+ - Populate base/referenceable/common properties into columns_struct via populate_common_columns.
4783
+ - Derive related properties using get_data_rel_elements_dict from the element body.
4784
+ - For each column in columns_struct, if its 'key' matches a key from the related dict, set its 'value'.
4785
+ - Return the enriched columns_struct.
4786
+ """
4787
+ # 1) Populate common columns first (header, properties, basic relationships, mermaid)
4788
+ col_data = populate_common_columns(element, columns_struct)
4789
+
4790
+ # 2) Build a map of related properties/elements from the body. The Data Designer methods
4791
+ # return a body that may include keys like assignedMeanings, otherRelatedElements,
4792
+ # memberOfCollections, memberDataFields, assignedDataClasses, nestedDataClasses, etc.
4793
+ try:
4794
+ related_map = self.get_data_rel_elements_dict(element)
4795
+ except Exception:
4796
+ related_map = {}
4797
+
4798
+ if isinstance(related_map, dict) and related_map:
4799
+ # 3) Walk the configured columns and overlay values when the key matches an entry from related_map
4800
+ try:
4801
+ formats = col_data.get("formats") if isinstance(col_data, dict) else None
4802
+ if isinstance(formats, list):
4803
+ targets = formats
4804
+ elif isinstance(formats, dict):
4805
+ # Handle dict variant. It may be a single format dict or a wrapper containing 'formats'.
4806
+ # Examples seen:
4807
+ # { 'columns': [...] }
4808
+ # { 'types': 'ALL', 'columns': [...] }
4809
+ # { 'formats': { 'columns': [...] } }
4810
+ inner = formats.get("formats") if isinstance(formats.get("formats"), dict | list) else None
4811
+ if isinstance(inner, list):
4812
+ targets = inner
4813
+ elif isinstance(inner, dict):
4814
+ targets = [inner]
4815
+ else:
4816
+ targets = [formats]
4817
+ else:
4818
+ targets = []
4819
+
4820
+ if targets:
4821
+ for fmt in targets:
4822
+ cols = fmt.get("columns", []) if isinstance(fmt, dict) else []
4823
+ for col in cols:
4824
+ key = col.get("key") if isinstance(col, dict) else None
4825
+ if key and key in related_map:
4826
+ col["value"] = related_map.get(key)
4827
+ else:
4828
+ # If columns are on the top-level (non-standard), attempt to handle gracefully
4829
+ cols = col_data.get("columns", []) if isinstance(col_data, dict) else []
4830
+ for col in cols:
4831
+ key = col.get("key") if isinstance(col, dict) else None
4832
+ if key and key in related_map:
4833
+ col["value"] = related_map.get(key)
4834
+ except Exception:
4835
+ # Do not fail rendering due to overlay issues; keep the base columns
4836
+ pass
4837
+
4838
+ return col_data
4796
4839
 
4797
4840
  def _generate_basic_structured_output(self, elements: dict, filter: str, type: str = None ,output_format: str = 'DICT',
4798
4841
  columns_struct: dict = None) -> str | list:
@@ -4942,6 +4985,12 @@ class DataDesigner(Client2):
4942
4985
  output_formats,
4943
4986
  )
4944
4987
 
4988
+ def _extract_additional_data_struct_properties(self, element, columns_struct):
4989
+ return None
4990
+ def _extract_additional_data_field_properties(self, element, columns_struct):
4991
+ return None
4992
+ def _extract_additional_data_class_properties(self, element, columns_struct):
4993
+ return None
4945
4994
 
4946
4995
  if __name__ == "__main__":
4947
4996
  print("Data Designer")
pyegeria/egeria_client.py CHANGED
@@ -24,7 +24,7 @@ from pyegeria.full_omag_server_config import FullServerConfig
24
24
  from pyegeria.metadata_explorer_omvs import MetadataExplorer
25
25
  from pyegeria.my_profile_omvs import MyProfile
26
26
  from pyegeria.feedback_manager_omvs import FeedbackManager
27
- from pyegeria.solution_architect_omvs import SolutionArchitect
27
+ from pyegeria.solution_architect import SolutionArchitect
28
28
  from pyegeria.server_operations import ServerOps
29
29
  from pyegeria.registered_info import RegisteredInfo
30
30
  from pyegeria.valid_metadata_omvs import ValidMetadataManager
@@ -12,11 +12,12 @@ from pyegeria.egeria_cat_client import EgeriaCat
12
12
  from pyegeria.metadata_explorer_omvs import MetadataExplorer
13
13
  from pyegeria.registered_info import RegisteredInfo
14
14
  from pyegeria.runtime_manager_omvs import RuntimeManager
15
- from pyegeria.solution_architect_omvs import SolutionArchitect
15
+ from pyegeria.solution_architect import SolutionArchitect
16
16
  from pyegeria.template_manager_omvs import TemplateManager
17
17
  from pyegeria.valid_metadata_omvs import ValidMetadataManager
18
18
  from pyegeria.governance_officer import GovernanceOfficer
19
19
  from pyegeria.collection_manager import CollectionManager
20
+ from pyegeria.external_references import ExternalReferences
20
21
  from pyegeria._globals import NO_ELEMENTS_FOUND
21
22
 
22
23
  class EgeriaTech:
@@ -65,6 +66,7 @@ class EgeriaTech:
65
66
  self._templates = TemplateManager(view_server, platform_url, user_id, user_pwd, token)
66
67
  self._gov_officer = GovernanceOfficer(view_server, platform_url, user_id, user_pwd, token)
67
68
  self._collections = CollectionManager(view_server, platform_url, user_id, user_pwd, token)
69
+ self._external_references = ExternalReferences(view_server, platform_url, user_id, user_pwd, token)
68
70
 
69
71
  self._subclients = [
70
72
  self._auto_curate,
@@ -79,6 +81,7 @@ class EgeriaTech:
79
81
  self._templates,
80
82
  self._gov_officer,
81
83
  self._collections,
84
+ self._external_references,
82
85
  ]
83
86
  self.NO_ELEMENTS_FOUND = NO_ELEMENTS_FOUND
84
87