pyegeria 5.4.0.28__py3-none-any.whl → 5.5.3.3__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.

Potentially problematic release.


This version of pyegeria might be problematic. Click here for more details.

Files changed (433) hide show
  1. commands/__init__.py +24 -0
  2. commands/cat/Dr-Egeria_md-orig.py +2 -2
  3. commands/cat/collection_actions.py +197 -0
  4. commands/cat/dr_egeria_command_help.py +137 -38
  5. commands/cat/dr_egeria_jupyter.py +7 -7
  6. commands/cat/dr_egeria_md.py +10 -267
  7. commands/cat/exp_list_glossaries.py +11 -14
  8. commands/cat/get_asset_graph.py +37 -267
  9. commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
  10. commands/cat/get_project_dependencies.py +14 -14
  11. commands/cat/get_project_structure.py +15 -14
  12. commands/cat/get_tech_type_elements.py +16 -116
  13. commands/cat/glossary_actions.py +145 -298
  14. commands/cat/list_assets.py +3 -11
  15. commands/cat/list_cert_types.py +17 -63
  16. commands/cat/list_collections.py +17 -139
  17. commands/cat/list_deployed_catalogs.py +15 -27
  18. commands/cat/list_deployed_database_schemas.py +27 -43
  19. commands/cat/list_deployed_databases.py +16 -31
  20. commands/cat/list_deployed_servers.py +35 -54
  21. commands/cat/list_glossaries.py +18 -17
  22. commands/cat/list_projects.py +10 -12
  23. commands/cat/list_tech_type_elements.py +21 -37
  24. commands/cat/list_tech_types.py +13 -25
  25. commands/cat/list_terms.py +38 -79
  26. commands/cat/list_todos.py +4 -11
  27. commands/cat/list_user_ids.py +3 -10
  28. commands/cat/my_reports.py +559 -0
  29. commands/cat/run_report.py +394 -0
  30. commands/cat/{list_format_set.py → run_report_orig.py} +136 -44
  31. commands/cli/egeria.py +182 -219
  32. commands/cli/egeria_cat.py +32 -59
  33. commands/cli/egeria_my.py +13 -0
  34. commands/cli/egeria_ops.py +69 -74
  35. commands/cli/egeria_tech.py +17 -93
  36. commands/{cat → deprecated}/list_data_designer.py +2 -4
  37. commands/{cat → deprecated}/list_data_structures_full.py +3 -6
  38. commands/deprecated/old_get_asset_graph.py +315 -0
  39. commands/my/__init__.py +0 -2
  40. commands/my/list_my_profile.py +27 -34
  41. commands/my/list_my_roles.py +1 -7
  42. commands/my/monitor_my_todos.py +1 -7
  43. commands/my/monitor_open_todos.py +6 -7
  44. commands/my/todo_actions.py +4 -5
  45. commands/ops/__init__.py +0 -2
  46. commands/ops/gov_server_actions.py +17 -21
  47. commands/ops/list_archives.py +17 -38
  48. commands/ops/list_catalog_targets.py +33 -40
  49. commands/ops/load_archive.py +14 -11
  50. commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
  51. commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
  52. commands/ops/monitor_engine_activity.py +79 -77
  53. commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
  54. commands/ops/monitor_platform_status.py +38 -50
  55. commands/ops/monitor_server_startup.py +6 -11
  56. commands/ops/monitor_server_status.py +7 -11
  57. commands/ops/orig_monitor_server_list.py +8 -8
  58. commands/ops/orig_monitor_server_status.py +1 -5
  59. commands/ops/refresh_integration_daemon.py +5 -5
  60. commands/ops/restart_integration_daemon.py +5 -5
  61. commands/ops/table_integ_daemon_status.py +6 -6
  62. commands/ops/x_engine_actions.py +7 -7
  63. commands/tech/__init__.py +0 -2
  64. commands/tech/{generic_actions.py → element_actions.py} +6 -11
  65. commands/tech/get_element_info.py +20 -29
  66. commands/tech/get_guid_info.py +23 -42
  67. commands/tech/get_tech_details.py +20 -35
  68. commands/tech/get_tech_type_template.py +28 -39
  69. commands/tech/list_all_om_type_elements.py +24 -30
  70. commands/tech/list_all_om_type_elements_x.py +22 -28
  71. commands/tech/list_all_related_elements.py +19 -28
  72. commands/tech/list_anchored_elements.py +22 -30
  73. commands/tech/list_asset_types.py +19 -24
  74. commands/tech/list_elements_by_classification_by_property_value.py +26 -32
  75. commands/tech/list_elements_by_property_value.py +19 -25
  76. commands/tech/list_elements_by_property_value_x.py +20 -28
  77. commands/tech/list_elements_for_classification.py +28 -41
  78. commands/tech/list_gov_action_processes.py +16 -27
  79. commands/tech/list_information_supply_chains.py +22 -30
  80. commands/tech/list_registered_services.py +14 -26
  81. commands/tech/list_related_elements_with_prop_value.py +15 -25
  82. commands/tech/list_related_specification.py +1 -4
  83. commands/tech/list_relationship_types.py +15 -25
  84. commands/tech/list_relationships.py +20 -36
  85. commands/tech/list_solution_blueprints.py +28 -33
  86. commands/tech/list_solution_components.py +23 -29
  87. commands/tech/list_solution_roles.py +21 -32
  88. commands/tech/list_tech_templates.py +51 -54
  89. commands/tech/list_valid_metadata_values.py +5 -9
  90. commands/tech/table_tech_templates.py +2 -6
  91. commands/tech/x_list_related_elements.py +1 -4
  92. examples/GeoSpatial Products Example.py +524 -0
  93. examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
  94. examples/Jupyter Notebooks/README.md +2 -0
  95. examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
  96. examples/Jupyter Notebooks/common/__init__.py +14 -0
  97. examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
  98. examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
  99. examples/Jupyter Notebooks/common/globals.ipynb +184 -0
  100. examples/Jupyter Notebooks/common/globals.py +154 -0
  101. examples/Jupyter Notebooks/common/orig_globals.py +152 -0
  102. examples/format_sets/all_format_sets.json +910 -0
  103. examples/format_sets/custom_format_sets.json +268 -0
  104. examples/format_sets/subset_format_sets.json +187 -0
  105. examples/format_sets_save_load_example.py +291 -0
  106. examples/jacquard_data_sets.py +129 -0
  107. examples/output_formats_example.py +193 -0
  108. examples/test_jacquard_data_sets.py +54 -0
  109. examples/test_jacquard_data_sets_scenarios.py +94 -0
  110. md_processing/__init__.py +33 -24
  111. md_processing/command_dispatcher.py +33 -0
  112. md_processing/command_mapping.py +221 -0
  113. md_processing/data/commands/commands_data_designer.json +537 -0
  114. md_processing/data/commands/commands_external_reference.json +733 -0
  115. md_processing/data/commands/commands_feedback.json +155 -0
  116. md_processing/data/commands/commands_general.json +204 -0
  117. md_processing/data/commands/commands_glossary.json +218 -0
  118. md_processing/data/commands/commands_governance.json +3678 -0
  119. md_processing/data/commands/commands_product_manager.json +865 -0
  120. md_processing/data/commands/commands_project.json +642 -0
  121. md_processing/data/commands/commands_solution_architect.json +366 -0
  122. md_processing/data/commands.json +6489 -30060
  123. md_processing/data/{commands-working.json → commands_working.json} +9304 -13513
  124. md_processing/data/gened_report_specs.py +6584 -0
  125. md_processing/data/generated_format_sets.json +6533 -0
  126. md_processing/data/generated_format_sets_old.json +4137 -0
  127. md_processing/data/generated_format_sets_old.py +45 -0
  128. md_processing/dr_egeria.py +182 -0
  129. md_processing/md_commands/data_designer_commands.py +195 -583
  130. md_processing/md_commands/ext_ref_commands.py +530 -0
  131. md_processing/md_commands/feedback_commands.py +726 -0
  132. md_processing/md_commands/glossary_commands.py +106 -490
  133. md_processing/md_commands/governance_officer_commands.py +129 -18
  134. md_processing/md_commands/product_manager_commands.py +362 -115
  135. md_processing/md_commands/project_commands.py +351 -134
  136. md_processing/md_commands/solution_architect_commands.py +276 -232
  137. md_processing/md_commands/view_commands.py +295 -0
  138. md_processing/md_processing_utils/common_md_proc_utils.py +258 -166
  139. md_processing/md_processing_utils/common_md_utils.py +138 -43
  140. md_processing/md_processing_utils/determine_width.py +103 -0
  141. md_processing/md_processing_utils/extraction_utils.py +100 -39
  142. md_processing/md_processing_utils/gen_report_specs.py +643 -0
  143. md_processing/md_processing_utils/generate_dr_help.py +61 -33
  144. md_processing/md_processing_utils/generate_md_cmd_templates.py +20 -19
  145. md_processing/md_processing_utils/generate_md_templates.py +3 -12
  146. md_processing/md_processing_utils/md_processing_constants.py +1053 -72
  147. pyegeria/__init__.py +203 -158
  148. pyegeria/core/__init__.py +40 -0
  149. pyegeria/core/_base_platform_client.py +574 -0
  150. pyegeria/core/_base_server_client.py +573 -0
  151. pyegeria/{_exceptions_new.py → core/_exceptions.py} +62 -30
  152. pyegeria/{_globals.py → core/_globals.py} +14 -3
  153. pyegeria/core/_server_client.py +6073 -0
  154. pyegeria/{_validators.py → core/_validators.py} +7 -8
  155. pyegeria/core/config.py +654 -0
  156. pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
  157. pyegeria/core/load_config.py +37 -0
  158. pyegeria/{logging_configuration.py → core/logging_configuration.py} +1 -1
  159. pyegeria/core/mcp_adapter.py +144 -0
  160. pyegeria/core/mcp_server.py +212 -0
  161. pyegeria/core/utils.py +405 -0
  162. pyegeria/{_client.py → deprecated/_client.py} +24 -25
  163. pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
  164. pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1987 -1877
  165. pyegeria/{output_formatter.py → deprecated/output_formatter_with_machine_keys.py} +298 -45
  166. pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +155 -171
  167. pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
  168. pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
  169. pyegeria/egeria_cat_client.py +26 -70
  170. pyegeria/egeria_client.py +130 -93
  171. pyegeria/egeria_config_client.py +40 -46
  172. pyegeria/egeria_tech_client.py +141 -54
  173. pyegeria/models/__init__.py +150 -0
  174. pyegeria/{models.py → models/models.py} +156 -20
  175. pyegeria/omvs/__init__.py +84 -0
  176. pyegeria/omvs/action_author.py +342 -0
  177. pyegeria/omvs/actor_manager.py +5980 -0
  178. pyegeria/omvs/asset_catalog.py +842 -0
  179. pyegeria/omvs/asset_maker.py +2736 -0
  180. pyegeria/omvs/automated_curation.py +4403 -0
  181. pyegeria/omvs/classification_manager.py +11213 -0
  182. pyegeria/{collection_manager.py → omvs/collection_manager.py} +1334 -1160
  183. pyegeria/omvs/community_matters_omvs.py +468 -0
  184. pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
  185. pyegeria/{data_designer.py → omvs/data_designer.py} +1115 -660
  186. pyegeria/omvs/data_discovery.py +869 -0
  187. pyegeria/omvs/data_engineer.py +372 -0
  188. pyegeria/omvs/digital_business.py +1133 -0
  189. pyegeria/omvs/external_links.py +1752 -0
  190. pyegeria/omvs/feedback_manager.py +834 -0
  191. pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
  192. pyegeria/{glossary_manager.py → omvs/glossary_manager.py} +857 -519
  193. pyegeria/{governance_officer.py → omvs/governance_officer.py} +964 -468
  194. pyegeria/omvs/lineage_linker.py +314 -0
  195. pyegeria/omvs/location_arena.py +1525 -0
  196. pyegeria/omvs/metadata_expert.py +668 -0
  197. pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
  198. pyegeria/omvs/my_profile.py +1042 -0
  199. pyegeria/omvs/notification_manager.py +358 -0
  200. pyegeria/omvs/people_organizer.py +394 -0
  201. pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
  202. pyegeria/omvs/product_manager.py +1825 -0
  203. pyegeria/omvs/project_manager.py +1907 -0
  204. pyegeria/omvs/reference_data.py +1140 -0
  205. pyegeria/omvs/registered_info.py +334 -0
  206. pyegeria/omvs/runtime_manager.py +2817 -0
  207. pyegeria/omvs/schema_maker.py +446 -0
  208. pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
  209. pyegeria/{solution_architect_omvs.py → omvs/solution_architect.py} +1886 -1505
  210. pyegeria/omvs/specification_properties.py +37 -0
  211. pyegeria/omvs/subject_area.py +1042 -0
  212. pyegeria/omvs/template_manager_omvs.py +236 -0
  213. pyegeria/omvs/time_keeper.py +1761 -0
  214. pyegeria/omvs/valid_metadata.py +3221 -0
  215. pyegeria/omvs/valid_metadata_lists.py +37 -0
  216. pyegeria/omvs/valid_type_lists.py +37 -0
  217. pyegeria/view/__init__.py +28 -0
  218. pyegeria/{_output_format_models.py → view/_output_format_models.py} +160 -24
  219. pyegeria/view/_output_formats.py +14 -0
  220. pyegeria/view/base_report_formats.py +2719 -0
  221. pyegeria/view/dr_egeria_reports.py +56 -0
  222. pyegeria/view/format_set_executor.py +397 -0
  223. pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
  224. pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
  225. pyegeria/view/output_formatter.py +1297 -0
  226. pyegeria-5.5.3.3.dist-info/METADATA +218 -0
  227. pyegeria-5.5.3.3.dist-info/RECORD +241 -0
  228. {pyegeria-5.4.0.28.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
  229. pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
  230. pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
  231. commands/cat/.DS_Store +0 -0
  232. commands/cat/.env +0 -8
  233. commands/cat/README.md +0 -16
  234. commands/cat/debug_log +0 -1126
  235. commands/cat/debug_log.2025-08-18_11-34-38_088636.zip +0 -0
  236. commands/cat/list_categories.py +0 -192
  237. commands/cat/logs/pyegeria.log +0 -4
  238. commands/cli/debug_log +0 -0
  239. commands/cli/debug_log.log +0 -0
  240. commands/cli/txt_custom_v2.tcss +0 -19
  241. commands/my/README.md +0 -17
  242. commands/ops/README.md +0 -24
  243. commands/ops/logs/pyegeria.log +0 -0
  244. commands/ops/monitor_asset_events.py +0 -108
  245. commands/tech/README.md +0 -24
  246. md_processing/.DS_Store +0 -0
  247. md_processing/dr-egeria-outbox/Collections-2025-08-12-13-30-37.md +0 -163
  248. md_processing/dr-egeria-outbox/Collections-2025-08-12-13-35-58.md +0 -474
  249. md_processing/dr_egeria_inbox/Derive-Dr-Gov-Defs.md +0 -8
  250. md_processing/dr_egeria_inbox/Dr.Egeria Templates.md +0 -873
  251. md_processing/dr_egeria_inbox/arch_test.md +0 -57
  252. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  253. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  254. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  255. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  256. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  257. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  258. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  259. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  260. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  261. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  262. md_processing/dr_egeria_inbox/collections.md +0 -39
  263. md_processing/dr_egeria_inbox/data_designer_debug.log +0 -6
  264. md_processing/dr_egeria_inbox/data_designer_out.md +0 -60
  265. md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
  266. md_processing/dr_egeria_inbox/data_field.md +0 -54
  267. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  268. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2406
  269. md_processing/dr_egeria_inbox/data_test.md +0 -179
  270. md_processing/dr_egeria_inbox/data_test2.md +0 -429
  271. md_processing/dr_egeria_inbox/data_test3.md +0 -462
  272. md_processing/dr_egeria_inbox/dr_egeria_data_designer_1.md +0 -124
  273. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  274. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  275. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -318
  276. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  277. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  278. md_processing/dr_egeria_inbox/generated_help_report.md +0 -9
  279. md_processing/dr_egeria_inbox/glossary_creation_experiment.ipynb +0 -341
  280. md_processing/dr_egeria_inbox/glossary_list.md +0 -5
  281. md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
  282. md_processing/dr_egeria_inbox/glossary_test1.md +0 -324
  283. md_processing/dr_egeria_inbox/gov_def.md +0 -482
  284. md_processing/dr_egeria_inbox/gov_def2.md +0 -447
  285. md_processing/dr_egeria_inbox/img.png +0 -0
  286. md_processing/dr_egeria_inbox/product.md +0 -211
  287. md_processing/dr_egeria_inbox/rel.md +0 -8
  288. md_processing/dr_egeria_inbox/sb.md +0 -119
  289. md_processing/dr_egeria_inbox/solution-components.md +0 -136
  290. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  291. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  292. md_processing/dr_egeria_inbox/t2.md +0 -268
  293. md_processing/dr_egeria_outbox/.obsidian/app.json +0 -1
  294. md_processing/dr_egeria_outbox/.obsidian/appearance.json +0 -1
  295. md_processing/dr_egeria_outbox/.obsidian/community-plugins.json +0 -6
  296. md_processing/dr_egeria_outbox/.obsidian/core-plugins.json +0 -31
  297. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/data.json +0 -10
  298. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/main.js +0 -4459
  299. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/manifest.json +0 -10
  300. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/data.json +0 -3
  301. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/main.js +0 -153
  302. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/manifest.json +0 -11
  303. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/styles.css +0 -1
  304. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/main.js +0 -500
  305. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +0 -12
  306. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/styles.css +0 -1
  307. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/main.js +0 -37
  308. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/manifest.json +0 -11
  309. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/styles.css +0 -220
  310. md_processing/dr_egeria_outbox/.obsidian/types.json +0 -28
  311. md_processing/dr_egeria_outbox/.obsidian/workspace.json +0 -220
  312. md_processing/dr_egeria_outbox/Untitled.canvas +0 -1
  313. md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:22-dr_egeria_intro_part1.md +0 -312
  314. md_processing/dr_egeria_outbox/friday/processed-2025-08-22 21:23-dr_egeria_intro_part1.md +0 -265
  315. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:06-dr_egeria_intro_part1.md +0 -230
  316. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:30-dr_egeria_intro_part1.md +0 -296
  317. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 15:31-dr_egeria_intro_part1.md +0 -253
  318. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:08-dr_egeria_intro_part2.md +0 -343
  319. md_processing/dr_egeria_outbox/friday/processed-2025-08-23 16:12-dr_egeria_intro_part2.md +0 -343
  320. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 07:05-product.md +0 -426
  321. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 07:56-product.md +0 -212
  322. md_processing/dr_egeria_outbox/monday/processed-2025-08-19 09:43-product.md +0 -201
  323. md_processing/dr_egeria_outbox/sunday/processed-2025-07-20 14:55-product.md +0 -77
  324. md_processing/dr_egeria_outbox/sunday/processed-2025-07-20 15:05-product.md +0 -75
  325. md_processing/dr_egeria_outbox/sunday/processed-2025-07-20 15:11-product.md +0 -74
  326. md_processing/dr_egeria_outbox/sunday/processed-2025-07-20 20:40-collections.md +0 -49
  327. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +0 -719
  328. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +0 -41
  329. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +0 -33
  330. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +0 -192
  331. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:08-gov_def2.md +0 -486
  332. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:10-gov_def2.md +0 -486
  333. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:53-gov_def2.md +0 -486
  334. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:54-gov_def2.md +0 -486
  335. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:03-gov_def2.md +0 -486
  336. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:06-gov_def2.md +0 -486
  337. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:10-gov_def2.md +0 -486
  338. md_processing/dr_egeria_outbox/tuesday/processed-2025-07-16 19:15-gov_def2.md +0 -527
  339. md_processing/dr_egeria_outbox/tuesday/processed-2025-07-17 12:08-gov_def2.md +0 -527
  340. md_processing/dr_egeria_outbox/tuesday/processed-2025-07-17 14:27-gov_def2.md +0 -485
  341. md_processing/dr_egeria_outbox/tuesday/processed-2025-08-19 10:55-product.md +0 -209
  342. md_processing/family_docs/Data Designer/Create_Data_Class.md +0 -164
  343. md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +0 -30
  344. md_processing/family_docs/Data Designer/Create_Data_Field.md +0 -162
  345. md_processing/family_docs/Data Designer/Create_Data_Specification.md +0 -36
  346. md_processing/family_docs/Data Designer/Create_Data_Structure.md +0 -38
  347. md_processing/family_docs/Data Designer/View_Data_Classes.md +0 -78
  348. md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +0 -78
  349. md_processing/family_docs/Data Designer/View_Data_Fields.md +0 -78
  350. md_processing/family_docs/Data Designer/View_Data_Specifications.md +0 -78
  351. md_processing/family_docs/Data Designer/View_Data_Structures.md +0 -78
  352. md_processing/family_docs/Data Designer.md +0 -842
  353. md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +0 -42
  354. md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +0 -36
  355. md_processing/family_docs/Digital Product Manager/Create_Agreement.md +0 -96
  356. md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +0 -72
  357. md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +0 -102
  358. md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +0 -134
  359. md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +0 -60
  360. md_processing/family_docs/Digital Product Manager/Link_Contracts.md +0 -26
  361. md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +0 -30
  362. md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +0 -48
  363. md_processing/family_docs/Digital Product Manager.md +0 -668
  364. md_processing/family_docs/Glossary/Attach_Category_Parent.md +0 -18
  365. md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +0 -26
  366. md_processing/family_docs/Glossary/Create_Category.md +0 -38
  367. md_processing/family_docs/Glossary/Create_Glossary.md +0 -42
  368. md_processing/family_docs/Glossary/Create_Term.md +0 -70
  369. md_processing/family_docs/Glossary.md +0 -206
  370. md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +0 -106
  371. md_processing/family_docs/Governance Officer/Create_Certification_Type.md +0 -112
  372. md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +0 -114
  373. md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +0 -114
  374. md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +0 -114
  375. md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +0 -128
  376. md_processing/family_docs/Governance Officer/Create_Governance_Process.md +0 -122
  377. md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +0 -106
  378. md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +0 -122
  379. md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +0 -122
  380. md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +0 -106
  381. md_processing/family_docs/Governance Officer/Create_License_Type.md +0 -112
  382. md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +0 -122
  383. md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +0 -106
  384. md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +0 -118
  385. md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +0 -114
  386. md_processing/family_docs/Governance Officer/Create_Security_Group.md +0 -120
  387. md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +0 -122
  388. md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +0 -106
  389. md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +0 -32
  390. md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +0 -32
  391. md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +0 -32
  392. md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +0 -82
  393. md_processing/family_docs/Governance Officer.md +0 -2412
  394. md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +0 -70
  395. md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +0 -44
  396. md_processing/family_docs/Solution Architect/Create_Solution_Component.md +0 -96
  397. md_processing/family_docs/Solution Architect/Create_Solution_Role.md +0 -66
  398. md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +0 -32
  399. md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +0 -32
  400. md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +0 -32
  401. md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +0 -32
  402. md_processing/family_docs/Solution Architect/View_Solution_Components.md +0 -32
  403. md_processing/family_docs/Solution Architect/View_Solution_Roles.md +0 -32
  404. md_processing/family_docs/Solution Architect.md +0 -490
  405. md_processing/md_processing_utils/debug_log +0 -574
  406. md_processing/md_processing_utils/debug_log.log +0 -0
  407. md_processing/md_processing_utils/dr-egeria-help-2025-07-17T17:22:09.md +0 -2065
  408. md_processing/md_processing_utils/generated_help_terms.md +0 -842
  409. pyegeria/.DS_Store +0 -0
  410. pyegeria/README.md +0 -35
  411. pyegeria/_client_new.py +0 -1102
  412. pyegeria/_output_formats.py +0 -730
  413. pyegeria/asset_catalog_omvs.py +0 -864
  414. pyegeria/automated_curation_omvs.py +0 -3765
  415. pyegeria/config.py +0 -523
  416. pyegeria/egeria_my_client.py +0 -91
  417. pyegeria/feedback_manager_omvs.py +0 -4573
  418. pyegeria/load_config_orig.py +0 -218
  419. pyegeria/md_processing_helpers.py +0 -58
  420. pyegeria/md_processing_utils_orig.py +0 -1103
  421. pyegeria/metadata_explorer_omvs.py +0 -2326
  422. pyegeria/my_profile_omvs.py +0 -1022
  423. pyegeria/project_manager.py +0 -1591
  424. pyegeria/registered_info.py +0 -167
  425. pyegeria/template_manager_omvs.py +0 -1414
  426. pyegeria/utils.py +0 -256
  427. pyegeria-5.4.0.28.dist-info/METADATA +0 -77
  428. pyegeria-5.4.0.28.dist-info/RECORD +0 -343
  429. pyegeria-5.4.0.28.dist-info/entry_points.txt +0 -105
  430. /commands/cat/debug_log.log → /pyegeria/deprecated/__init__.py +0 -0
  431. /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
  432. /pyegeria/{collection_models.py → models/collection_models.py} +0 -0
  433. {pyegeria-5.4.0.28.dist-info → pyegeria-5.5.3.3.dist-info/licenses}/LICENSE +0 -0
@@ -1,28 +1,31 @@
1
1
  from datetime import datetime
2
2
  import re
3
3
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
4
- from pyegeria.utils import (camel_to_title_case)
4
+ from pyegeria.core.utils import (camel_to_title_case)
5
5
  from markdown_it import MarkdownIt
6
6
  from rich.console import Console
7
7
  from loguru import logger
8
+ from pyegeria.core.config import settings
8
9
 
9
- from pyegeria.mermaid_utilities import construct_mermaid_web
10
- from pyegeria._output_formats import select_output_format_set, MD_SEPARATOR
10
+ from pyegeria.view.mermaid_utilities import construct_mermaid_web
11
+ from pyegeria.view.base_report_formats import select_report_format, MD_SEPARATOR, get_report_spec_match
11
12
  from pyegeria.models import to_camel_case
12
13
 
13
14
  """
14
- Note on select_output_format_set function:
15
+ Note on select_report_spec function:
15
16
 
16
17
  This function and related data structures have been moved back to _output_formats.py.
17
- Please import select_output_format_set from pyegeria._output_formats instead of from this module.
18
+ Please import select_report_spec from pyegeria._output_formats instead of from this module.
18
19
  """
19
20
 
20
- console = Console(width= 250)
21
+ console = Console(width=settings.Environment.console_width)
21
22
 
22
23
 
23
24
  def _extract_referenceable_properties(element: dict[str, Any]) -> dict[str, Any]:
24
25
  # Get general header attributes
25
- guid = element['elementHeader'].get("guid", None)
26
+ guid = element.get('elementHeader', {}).get("guid", None)
27
+ if guid is None:
28
+ return {}
26
29
  metadata_collection_id = element['elementHeader']['origin'].get("homeMetadataCollectionId", None)
27
30
  metadata_collection_name = element['elementHeader']['origin'].get("homeMetadataCollectionName", None)
28
31
  origin_category = element['elementHeader'].get("origin_category", None)
@@ -196,13 +199,13 @@ def make_md_attribute(attribute_name: str, attribute_value: str, output_type: st
196
199
  attribute_title = ""
197
200
 
198
201
  if output_type in ["FORM", "MD"]:
199
- if attribute_name.lower() in [ "mermaid", "links", "implemented by", "sub_components"]:
202
+ if attribute_name.lower() in [ "mermaid", "solutionBlueprintMermaidGraph", "links", "implemented by", "sub_components"]:
200
203
  return '\n'
201
204
 
202
205
  output = f"## {attribute_title}\n{attribute_value}\n\n"
203
- elif output_type == "REPORT":
204
- if attribute_title in ['Mermaid Graph', 'Mermaid']:
205
- output = f"## Mermaid Graph\n\n```mermaid\n{attribute_value}\n```\n"
206
+ elif output_type in ["REPORT", "MERMAID"]:
207
+ if attribute_title in ['Mermaid Graph', 'Mermaid', 'Solution Blueprint Mermaid Graph']:
208
+ output = f"## {attribute_title}\n\n```mermaid\n{attribute_value}\n```\n"
206
209
  elif attribute_value:
207
210
  output = f"## {attribute_title}\n{attribute_value}\n\n"
208
211
  return output
@@ -234,7 +237,7 @@ def populate_columns_from_properties(element: dict, columns_struct: dict) -> dic
234
237
  Populate a columns_struct with values from the element's properties.
235
238
 
236
239
  The element dict is expected to have a nested 'properties' dict whose keys are in camelCase.
237
- The columns_struct is expected to follow the format returned by select_output_format_set, where
240
+ The columns_struct is expected to follow the format returned by select_report_spec, where
238
241
  columns are located at columns_struct['formats']['columns'] and each column is a dict containing
239
242
  at least a 'key' field expressed in snake_case. For each column whose snake_case key corresponds
240
243
  to a key in the element properties (after converting to camelCase), this function adds a 'value'
@@ -255,9 +258,9 @@ def populate_columns_from_properties(element: dict, columns_struct: dict) -> dic
255
258
  if not isinstance(props, dict):
256
259
  return columns_struct
257
260
 
258
- # Get the columns list if present
261
+ # Get the attributes list if present
259
262
  formats = columns_struct.get('formats') or {}
260
- columns = formats.get('columns') if isinstance(formats, dict) else None
263
+ columns = formats.get('attributes') if isinstance(formats, dict) else None
261
264
  if not isinstance(columns, list):
262
265
  return columns_struct
263
266
 
@@ -303,7 +306,7 @@ def get_required_relationships(element: dict, columns_struct: dict) -> dict:
303
306
  return columns_struct
304
307
 
305
308
  formats = columns_struct.get('formats') or {}
306
- columns = formats.get('columns') if isinstance(formats, dict) else None
309
+ columns = formats.get('attributes') if isinstance(formats, dict) else None
307
310
  if not isinstance(columns, list):
308
311
  return columns_struct
309
312
 
@@ -400,10 +403,10 @@ def generate_entity_md(elements: List[Dict],
400
403
  """
401
404
  heading = columns_struct.get("heading")
402
405
  if heading == "Default Base Attributes":
403
- elements_md = "## Reporting on Default Base Attributes - Perhaps couldn't find a valid combination of output_format_set and output_format?\n\n"
406
+ elements_md = "## Reporting on Default Base Attributes - Perhaps couldn't find a valid combination of report_spec and output_format?\n\n"
404
407
  else:
405
408
  elements_md = ""
406
- base_columns = columns_struct['formats'].get('columns') if columns_struct else None
409
+ base_columns = columns_struct['formats'].get('attributes') if columns_struct else None
407
410
 
408
411
  for element in elements:
409
412
  if element is None:
@@ -434,7 +437,7 @@ def generate_entity_md(elements: List[Dict],
434
437
  # Determine display name
435
438
  display_name = None
436
439
  if returned_struct is not None:
437
- cols = returned_struct.get('formats', {}).get('columns', [])
440
+ cols = returned_struct.get('formats', {}).get('attributes', [])
438
441
  # Find value from 'display_name' or 'title'
439
442
  for col in cols:
440
443
  if col.get('key') in ('display_name', 'title'):
@@ -458,7 +461,7 @@ def generate_entity_md(elements: List[Dict],
458
461
 
459
462
  # Add attributes based on column spec if available, otherwise, add all (legacy)
460
463
  if returned_struct is not None:
461
- cols = returned_struct.get('formats', {}).get('columns', [])
464
+ cols = returned_struct.get('formats', {}).get('attributes', [])
462
465
  for column in cols:
463
466
  name = column.get('name')
464
467
  key = column.get('key')
@@ -468,7 +471,7 @@ def generate_entity_md(elements: List[Dict],
468
471
  if column.get('format'):
469
472
  value = format_for_markdown_table(value, guid)
470
473
  elements_md += make_md_attribute(name, value, output_format)
471
- if wk := returned_struct.get("annotations", {}).get("wikilinks"):
474
+ if wk := returned_struct.get("annotations", {}).get("wikilinks", None):
472
475
  elements_md += ", ".join(wk)
473
476
  elif base_columns:
474
477
  # If we have columns but extractor didn't return struct, use legacy props lookup
@@ -525,11 +528,18 @@ def generate_entity_md_table(elements: List[Dict],
525
528
  str: Markdown table
526
529
  """
527
530
  # Handle pluralization - if entity_type ends with 'y', use 'ies' instead of 's'
528
- entity_type_plural = f"{entity_type[:-1]}ies" if entity_type.endswith('y') else f"{entity_type}s"
529
- columns = columns_struct['formats'].get('columns', [])
531
+ target_type = columns_struct.get('target_type', entity_type)
532
+ # if target_type.endswith('y'):
533
+ # target_type = target_type.replace('y', 'ies')
534
+ # else:
535
+ # target_type = target_type.replace('s', 's')
536
+
537
+ entity_type_plural = f"{target_type[:-1]}ies" if target_type.endswith('y') else f"{target_type}s"
538
+ # entity_type_plural = target_type
539
+ columns = columns_struct['formats'].get('attributes', [])
530
540
  heading = columns_struct.get("heading")
531
541
  if heading == "Default Base Attributes":
532
- elements_md = "## Reporting on Default Base Attributes - Perhaps couldn't find a valid combination of output_format_set and output_format?\n\n"
542
+ elements_md = "## Reporting on Default Base Attributes - Perhaps couldn't find a valid combination of report_spec and output_format?\n\n"
533
543
  else:
534
544
  elements_md = ""
535
545
 
@@ -549,7 +559,7 @@ def generate_entity_md_table(elements: List[Dict],
549
559
 
550
560
  # Add rows
551
561
  for element in elements:
552
- guid = element.get('elementHeader', {}).get('guid')
562
+ guid = element.get('elementHeader', {}).get('guid', None)
553
563
 
554
564
  # Extractor returns columns_struct with values when possible
555
565
  try:
@@ -559,7 +569,7 @@ def generate_entity_md_table(elements: List[Dict],
559
569
 
560
570
  # For help mode, bypass extraction
561
571
  if output_format == "help":
562
- returned_struct = {"formats": {"columns": columns}}
572
+ returned_struct = {"formats": {"attributes": columns}}
563
573
 
564
574
  # Additional props (if any)
565
575
  additional_props = {}
@@ -569,7 +579,7 @@ def generate_entity_md_table(elements: List[Dict],
569
579
  # Build row
570
580
  row = "| "
571
581
  if returned_struct is not None:
572
- for column in returned_struct.get('formats', {}).get('columns', []):
582
+ for column in returned_struct.get('formats', {}).get('attributes', []):
573
583
  key = column.get('key')
574
584
  value = column.get('value')
575
585
  if (value in (None, "")) and key in additional_props:
@@ -592,8 +602,8 @@ def generate_entity_md_table(elements: List[Dict],
592
602
  row += f"{value} | "
593
603
 
594
604
  elements_md += row + "\n"
595
- if wk := columns_struct.get("annotations",{}).get("wikilinks", None):
596
- elements_md += ", ".join(wk)
605
+ # if wk := columns_struct.get("annotations",{}).get("wikilinks", None):
606
+ # elements_md += ", ".join(wk)
597
607
  return elements_md
598
608
 
599
609
  def generate_entity_dict(elements: List[Dict],
@@ -644,9 +654,9 @@ def generate_entity_dict(elements: List[Dict],
644
654
  # Create entity dictionary
645
655
  entity_dict = {}
646
656
 
647
- columns = columns_struct['formats'].get('columns', None) if columns_struct else None
657
+ columns = columns_struct['formats'].get('attributes', None) if columns_struct else None
648
658
  if returned_struct is not None:
649
- for column in returned_struct.get('formats', {}).get('columns', []):
659
+ for column in returned_struct.get('formats', {}).get('attributes', []):
650
660
  key = column.get('key')
651
661
  name = column.get('name')
652
662
  value = column.get('value')
@@ -654,7 +664,18 @@ def generate_entity_dict(elements: List[Dict],
654
664
  value = additional_props[key]
655
665
  if column.get('format'):
656
666
  value = format_for_markdown_table(value, guid)
657
- entity_dict[name] = value
667
+ # Use machine key for DICT output to avoid name collisions (e.g., multiple 'GUID' display names)
668
+ dict_key = key or name
669
+ # If the key already exists and differs only by case, preserve both by preferring exact key
670
+ if dict_key in entity_dict and name and name != dict_key:
671
+ # suffix with _1 to avoid overwrite
672
+ suffix_idx = 1
673
+ tmp_key = f"{dict_key}_{suffix_idx}"
674
+ while tmp_key in entity_dict:
675
+ suffix_idx += 1
676
+ tmp_key = f"{dict_key}_{suffix_idx}"
677
+ dict_key = tmp_key
678
+ entity_dict[dict_key] = value
658
679
  elif columns:
659
680
  for column in columns:
660
681
  key = column['key']
@@ -667,9 +688,17 @@ def generate_entity_dict(elements: List[Dict],
667
688
  value = additional_props[key]
668
689
  if column.get('format', None):
669
690
  value = format_for_markdown_table(value, guid or props.get('GUID'))
670
- entity_dict[name] = value
691
+ dict_key = key or name
692
+ if dict_key in entity_dict and name and name != dict_key:
693
+ suffix_idx = 1
694
+ tmp_key = f"{dict_key}_{suffix_idx}"
695
+ while tmp_key in entity_dict:
696
+ suffix_idx += 1
697
+ tmp_key = f"{dict_key}_{suffix_idx}"
698
+ dict_key = tmp_key
699
+ entity_dict[dict_key] = value
671
700
  else:
672
- props = extract_properties_func(element)
701
+ props = extract_properties_func(element, columns_struct)
673
702
  # Add properties based on include/exclude lists
674
703
  for key, value in props.items():
675
704
  if key not in ['properties', 'mermaid']: # Skip the raw properties object
@@ -713,6 +742,139 @@ def generate_entity_dict(elements: List[Dict],
713
742
 
714
743
  return result
715
744
 
745
+ def resolve_output_formats(entity_type: str,
746
+ output_format: str,
747
+ report_spec: Optional[Union[str, dict]] = None,
748
+ default_label: Optional[str] = None,
749
+ **kwargs) -> Optional[dict]:
750
+ """
751
+ Resolve a report format structure given an entity type, the desired output format
752
+ (e.g., DICT, LIST, MD, REPORT, FORM), and either a label (str) or a dict of format sets.
753
+
754
+ Backward compatibility:
755
+ - Accepts legacy kwarg 'report_spec' and treats it as report_spec.
756
+
757
+ Selection order:
758
+ - If report_spec is a str: select by label.
759
+ - If report_spec is a dict: use get_report_spec_match to pick a matching format.
760
+ - Else: try selecting by entity_type or default_label.
761
+ - Fallback: select "Default".
762
+ """
763
+ from pyegeria.view.base_report_formats import get_report_spec_match
764
+
765
+ if report_spec is None and isinstance(kwargs, dict):
766
+ if 'report_spec' in kwargs:
767
+ report_spec = kwargs.get('report_spec')
768
+ elif 'report_format' in kwargs:
769
+ report_spec = kwargs.get('report_format')
770
+ elif 'output_format_spec' in kwargs:
771
+ report_spec = kwargs.get('output_format_spec')
772
+
773
+ if isinstance(report_spec, str):
774
+ return select_report_format(report_spec, output_format)
775
+ if isinstance(report_spec, dict):
776
+ return get_report_spec_match(report_spec, output_format)
777
+
778
+ label = default_label or entity_type
779
+ fmt = select_report_format(label, output_format)
780
+ if fmt is None:
781
+ fmt = select_report_format("Default", output_format)
782
+ return fmt
783
+
784
+
785
+ def overlay_additional_values(columns_struct: dict, extra: Optional[dict]) -> dict:
786
+ """
787
+ Overlay extra values into columns_struct only where the column's value is empty or missing.
788
+ Returns the modified columns_struct.
789
+ """
790
+ if not isinstance(columns_struct, dict) or not extra:
791
+ return columns_struct
792
+ columns = columns_struct.get('formats', {}).get('attributes')
793
+ if not isinstance(columns, list):
794
+ return columns_struct
795
+ for col in columns:
796
+ if not isinstance(col, dict):
797
+ continue
798
+ key = col.get('key')
799
+ if not key:
800
+ continue
801
+ if col.get('value') in (None, "") and key in extra:
802
+ col['value'] = extra[key]
803
+ return columns_struct
804
+
805
+
806
+ def populate_common_columns(
807
+ element: dict,
808
+ columns_struct: dict,
809
+ *,
810
+ include_header: bool = True,
811
+ include_relationships: bool = True,
812
+ include_subject_area: bool = True,
813
+ mermaid_source_key: str = 'mermaidGraph',
814
+ mermaid_dest_key: str = 'mermaid'
815
+ ) -> dict:
816
+ """
817
+ Populate the common columns in columns_struct based on a standard Egeria element shape.
818
+
819
+ Steps:
820
+ - Populate from element.properties (camelCase mapped from snake_case keys)
821
+ - Optionally overlay header-derived values (GUID, type_name, times, etc.)
822
+ - Optionally populate relationship-based columns via get_required_relationships
823
+ - Optionally populate subject_area from element.elementHeader.subjectArea.classificationProperties.subjectAreaName
824
+ - If a column with key == mermaid_dest_key is present, set it from mermaid_source_key
825
+ - Do not overwrite non-empty values already set
826
+ """
827
+ # 1) Base properties
828
+ col_data = populate_columns_from_properties(element, columns_struct)
829
+ columns_list = col_data.get('formats', {}).get('attributes', [])
830
+
831
+ # 2) Header overlay
832
+ header_props = _extract_referenceable_properties(element) if include_header else {}
833
+ guid = header_props.get('GUID') if include_header else None
834
+ if include_header:
835
+ for column in columns_list:
836
+ if not isinstance(column, dict):
837
+ continue
838
+ key = column.get('key')
839
+ if not key:
840
+ continue
841
+ if column.get('value') not in (None, ""):
842
+ continue
843
+ if key in header_props:
844
+ column['value'] = header_props.get(key)
845
+ elif isinstance(key, str) and key.lower() == 'guid':
846
+ column['value'] = guid
847
+
848
+ # 3) Relationships
849
+ if include_relationships:
850
+ col_data = get_required_relationships(element, col_data)
851
+
852
+ # 4) Subject area
853
+ if include_subject_area:
854
+ try:
855
+ subject_area = element.get('elementHeader', {}).get('subjectArea') or ""
856
+ subj_val = ""
857
+ if isinstance(subject_area, dict):
858
+ subj_val = subject_area.get('classificationProperties', {}).get('subjectAreaName', '')
859
+ for column in columns_list:
860
+ if column.get('key') == 'subject_area' and column.get('value') in (None, ""):
861
+ column['value'] = subj_val
862
+ except Exception as e:
863
+ logger.debug(f"populate_common_columns: subject_area handling error: {e}")
864
+
865
+ # 5) Mermaid
866
+ try:
867
+ mermaid_val = element.get(mermaid_source_key, '') or ''
868
+ for column in columns_list:
869
+ if column.get('key') == mermaid_dest_key and column.get('value') in (None, ""):
870
+ column['value'] = mermaid_val
871
+ break
872
+ except Exception as e:
873
+ logger.debug(f"populate_common_columns: mermaid handling error: {e}")
874
+
875
+ return col_data
876
+
877
+
716
878
  def extract_mermaid_only(elements: Union[Dict, List[Dict]]) -> Union[str, List[str]]:
717
879
  """
718
880
  Extract mermaid graph data from elements.
@@ -724,11 +886,18 @@ def extract_mermaid_only(elements: Union[Dict, List[Dict]]) -> Union[str, List[s
724
886
  String or list of strings containing mermaid graph data
725
887
  """
726
888
  if isinstance(elements, dict):
727
- return elements.get('mermaidGraph', '___')
889
+ mer = elements.get('mermaidGraph', None)
890
+ if mer:
891
+ return f"\n```mermaid\n{mer}\n```"
892
+ else:
893
+ return "---"
894
+
728
895
 
729
896
  result = []
730
897
  for element in elements:
731
- result.append(element.get('mermaidGraph', '___'))
898
+ mer = element.get('mermaidGraph', "---")
899
+ mer_out = f"\n\n```mermaid\n{mer}\n```" if mer else "---"
900
+ result.append(mer_out)
732
901
  return result
733
902
 
734
903
  def extract_basic_dict(elements: Union[Dict, List[Dict]]) -> Union[Dict, List[Dict]]:
@@ -779,13 +948,57 @@ def extract_basic_dict(elements: Union[Dict, List[Dict]]) -> Union[Dict, List[Di
779
948
  result.append(body)
780
949
  return result
781
950
 
782
- def generate_output(elements: Union[Dict, List[Dict]],
783
- search_string: str,
784
- entity_type: str,
785
- output_format: str,
786
- extract_properties_func: Callable,
787
- get_additional_props_func: Optional[Callable] = None,
788
- columns_struct: dict = None) -> Union[str, list[dict]]:
951
+ def _extract_default_properties(self, element: dict, columns_struct: dict) -> dict:
952
+ props = element.get('properties', {}) or {}
953
+ normalized = {
954
+ 'properties': props,
955
+ 'elementHeader': element.get('elementHeader', {}),
956
+ }
957
+ # Common population pipeline
958
+ col_data = populate_common_columns(element, columns_struct)
959
+ columns_list = col_data.get('formats', {}).get('attributes', [])
960
+
961
+ return col_data
962
+
963
+
964
+ def _generate_default_output(self, elements: dict | list[dict], search_string: str,
965
+ element_type_name: str | None,
966
+ output_format: str = 'DICT',
967
+ report_format: dict | str | None = None,
968
+ **kwargs) -> str | list[dict]:
969
+ entity_type = 'Referenceable'
970
+ # Backward compatibility: accept legacy kwarg
971
+ if report_format is None and isinstance(kwargs, dict) and 'report_spec' in kwargs:
972
+ report_format = kwargs.get('report_spec')
973
+ if report_format:
974
+ if isinstance(report_format, str):
975
+ output_formats = select_report_format(report_format, output_format)
976
+ elif isinstance(report_format, dict):
977
+ output_formats = get_report_spec_match(report_format, output_format)
978
+ else:
979
+ output_formats = None
980
+ else:
981
+ output_formats = select_report_format(entity_type, output_format)
982
+ if output_formats is None:
983
+ output_formats = select_report_format('Default', output_format)
984
+ return generate_output(
985
+ elements=elements,
986
+ search_string=search_string,
987
+ entity_type=entity_type,
988
+ output_format=output_format,
989
+ extract_properties_func=_extract_default_properties,
990
+ get_additional_props_func=None,
991
+ columns_struct=output_formats,
992
+ )
993
+
994
+
995
+ def generate_output(elements: Union[Dict, List[Dict]],
996
+ search_string: str,
997
+ entity_type: str,
998
+ output_format: str,
999
+ extract_properties_func: Callable,
1000
+ get_additional_props_func: Optional[Callable] = None,
1001
+ columns_struct: dict = None) -> Union[str, list[dict]]:
789
1002
  """
790
1003
  Generate output in the specified format for the given elements.
791
1004
 
@@ -801,7 +1014,15 @@ def generate_output(elements: Union[Dict, List[Dict]],
801
1014
  Returns:
802
1015
  Formatted output as string or list of dictionaries
803
1016
  """
804
- columns = columns_struct['formats'].get('columns',None) if columns_struct else None
1017
+ columns = columns_struct['formats'].get('attributes',None) if columns_struct else None
1018
+ if not columns:
1019
+ columns_struct = select_report_format("Default",output_format)
1020
+ if columns_struct:
1021
+ columns = columns_struct.get('formats', {}).get('attributes', None)
1022
+
1023
+ target_type = columns_struct.get('target_type', entity_type) if columns_struct else entity_type
1024
+ if target_type is None:
1025
+ target_type = entity_type
805
1026
 
806
1027
  # Ensure elements is a list
807
1028
  if isinstance(elements, dict):
@@ -811,6 +1032,10 @@ def generate_output(elements: Union[Dict, List[Dict]],
811
1032
  if search_string is None or search_string == '':
812
1033
  search_string = "All"
813
1034
 
1035
+ # Set the output format to DICT to return values to table display
1036
+ if output_format == "TABLE":
1037
+ output_format = "DICT"
1038
+
814
1039
  # Generate output based on format
815
1040
  if output_format == 'MERMAID':
816
1041
  return extract_mermaid_only(elements)
@@ -856,7 +1081,7 @@ def generate_output(elements: Union[Dict, List[Dict]],
856
1081
 
857
1082
  else: # MD, FORM, REPORT
858
1083
  elements_md, elements_action = make_preamble(
859
- obj_type=entity_type,
1084
+ obj_type=target_type,
860
1085
  search_string=search_string,
861
1086
  output_format=output_format
862
1087
  )
@@ -865,10 +1090,38 @@ def generate_output(elements: Union[Dict, List[Dict]],
865
1090
  elements=elements,
866
1091
  elements_action=elements_action,
867
1092
  output_format=output_format,
868
- entity_type=entity_type,
1093
+ entity_type=target_type,
869
1094
  extract_properties_func=extract_properties_func,
870
1095
  get_additional_props_func=get_additional_props_func,
871
1096
  columns_struct = columns_struct
872
1097
  )
873
1098
 
874
1099
  return elements_md
1100
+
1101
+ # Machine keys explanation
1102
+ # -------------------------
1103
+ # In pyegeria’s reporting system, each output column is defined with two identifiers:
1104
+ # - name: the human-readable display label (e.g., "GUID", "Display Name") shown in tables and reports.
1105
+ # - key: the stable, programmatic identifier (usually snake_case, e.g., guid, display_name) used internally.
1106
+ #
1107
+ # We refer to the key as the machine key. It is intended to be:
1108
+ # - Unique within a given row/spec: so downstream code can unambiguously reference values.
1109
+ # - Stable over time: it should not change with presentation tweaks or localization.
1110
+ # - Program-friendly: lowercase with underscores, matching the data model or derivation (e.g., header vs properties).
1111
+ #
1112
+ # Why DICT output uses machine keys
1113
+ # - Display names are for humans and may repeat across different sources of data in one row. For example,
1114
+ # Collections may include a GUID from the element header (key: guid, display name: "GUID") and a related member GUID
1115
+ # (key: GUID, display name: "GUID"). If the DICT used display names, one would overwrite the other.
1116
+ # - By using the machine key (column['key']) as the dictionary key, DICT output avoids these collisions and remains
1117
+ # deterministic for programmatic consumers.
1118
+ #
1119
+ # Collision handling
1120
+ # - If, within an unusual spec, two columns share the same key, DICT generation adds a numeric suffix (e.g., guid_1)
1121
+ # to preserve both values. This is a safeguard and such collisions should be avoided in specs.
1122
+ #
1123
+ # Guidance for spec authors
1124
+ # - Choose clear, stable machine keys in snake_case that map to actual data fields or well-defined derivations.
1125
+ # - Reserve display names for presentation; do not rely on them for programmatic access.
1126
+ # - When you need two visually identical labels (e.g., both "GUID"), ensure their keys differ (e.g., guid vs GUID) to
1127
+ # reflect different sources/semantics.