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
@@ -0,0 +1,2719 @@
1
+ """
2
+ SPDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+ """
5
+
6
+ """
7
+ # Purpose
8
+ This file manages output format sets.
9
+
10
+ pyegeria allows find and get requests to generate output in different output formats -
11
+ including DICT, MD, FORM, REPORT, LIST, MERMAID, TABLE, and perhaps additional ones in the future.
12
+
13
+ It is important to be able to filter which attributes to
14
+ display, and the order in which they appear. However, many, if not most users will likely not want to customize
15
+ the column list and so we need a sensible set of defaults for each type of output. These defaults are used
16
+ by the find and get methods if the user doesn't provide a value for the columns parameter.
17
+
18
+ This file contains these defaults and functions to work with them. The output format sets are now implemented
19
+ using Pydantic models defined in `_output_format_models.py`, which provide several advantages:
20
+ - Type validation: The models ensure that the data has the correct types and structure.
21
+ - Composition: The models support composition of formats, allowing formats to be reused and combined.
22
+ - Documentation: The models provide clear documentation of the data structure.
23
+ - IDE support: The models provide better IDE support, including autocompletion and type hints.
24
+
25
+ The functions in this module are designed to be backward compatible with code that expects the old
26
+ dictionary-based format. They convert between Pydantic models and dictionaries as needed.
27
+
28
+ Example usage:
29
+ ```python
30
+ # Get a format set by name and output type
31
+ format_set = select_report_spec("Collections", "TABLE")
32
+
33
+ # Get a list of all available format sets
34
+ format_sets = report_spec_list()
35
+
36
+ # Get the heading and description of a format set
37
+ heading = get_report_spec_heading("Collections")
38
+ description = get_report_spec_description("Collections")
39
+
40
+ # Match a format set with a specific output type
41
+ matched_format_set = get_report_spec_match(format_set, "DICT")
42
+ ```
43
+
44
+ For more advanced usage, you can work directly with the Pydantic models:
45
+ ```python
46
+ from pyegeria._output_format_models import Column, Format, FormatSet
47
+
48
+ # Create a new format set
49
+ format_set = FormatSet(
50
+ target_type="Example",
51
+ heading="Example Format Set",
52
+ description="An example format set",
53
+ formats=[
54
+ Format(
55
+ types=["TABLE", "DICT"],
56
+ attributes=[
57
+ Column(name="Display Name", key="display_name"),
58
+ Column(name="Description", key="description", format=True),
59
+ ],
60
+ ),
61
+ ],
62
+ )
63
+
64
+ # Add the format set to the report_specs dictionary
65
+ report_specs["Example"] = format_set
66
+ ```
67
+
68
+ Exceptions
69
+ ----------
70
+ This module may raise the following exceptions:
71
+ - ReportFormatCollision: Raised when duplicate report spec labels are detected while
72
+ combining built-in, generated, config-loaded, or runtime format sets.
73
+ - FileNotFoundError: Raised when a configured JSON file containing report specs cannot be found.
74
+ - ImportError | AttributeError: Raised when a configured module function for loading
75
+ report specs cannot be imported or resolved.
76
+ - KeyError: Raised when accessing a non-existent report spec label (e.g., direct dict access).
77
+ - ValueError: Raised for invalid or unsupported output types, or malformed structures.
78
+ - pydantic.ValidationError: Raised when constructing `FormatSet`/`Format`/`Attribute`
79
+ instances with invalid data.
80
+ """
81
+
82
+ import os
83
+ from pathlib import Path
84
+ from typing import List, Union
85
+
86
+ from loguru import logger
87
+
88
+ from pyegeria.view._output_format_models import (
89
+ Attribute,
90
+ Column,
91
+ Format,
92
+ ActionParameter,
93
+ FormatSet,
94
+ FormatSetDict
95
+ )
96
+
97
+ # Import generated format sets from within pyegeria package
98
+ try:
99
+ from pyegeria.view.dr_egeria_reports import generated_format_sets
100
+
101
+ logger.debug(f"Loaded {len(generated_format_sets)} generated format sets from pyegeria.dr_egeria_reports")
102
+ except (ImportError) as e:
103
+ logger.debug(f"No pyegeria.dr_egeria_reports module found, using empty set: {e}")
104
+ generated_format_sets = FormatSetDict()
105
+
106
+
107
+ # from pyegeria.config import settings
108
+
109
+ def combine_format_set_dicts(dict1: dict, dict2: dict) -> dict:
110
+ """
111
+ Combine two FormatSetDicts, merging their contents.
112
+
113
+ Args:
114
+ dict1 (dict): The first FormatSetDict.
115
+ dict2 (dict): The second FormatSetDict.
116
+
117
+ Returns:
118
+ dict: A new dictionary combining both, with keys from dict2
119
+ overwriting keys from dict1 in case of conflicts.
120
+ """
121
+ combined = dict1.copy() # Start with dict1
122
+ for key, value in dict2.items():
123
+ if key in combined:
124
+ if isinstance(combined[key], dict) and isinstance(value, dict):
125
+ # Recursively merge if both values are dictionaries
126
+ combined[key] = combine_format_set_dicts(combined[key], value)
127
+ else:
128
+ # Otherwise, overwrite with dict2's value.
129
+ combined[key] = value
130
+ else:
131
+ # Key from dict2 doesn't exist in dict1, add it
132
+ combined[key] = value
133
+ return combined
134
+
135
+
136
+ # Get the configured value for the user format sets directory
137
+
138
+ # USER_FORMAT_SETS_DIR = os.path.expanduser(settings.Environment.pyegeria_user_report_specs_dir)
139
+ # Prefer new env var, fallback to old for backward compatibility
140
+ USER_FORMAT_SETS_DIR = os.getenv("PYEGERIA_USER_REPORT_SPECS_DIR", os.getenv("PYEGERIA_USER_FORMAT_SETS_DIR", "../"))
141
+ # Constants
142
+ MD_SEPARATOR = "\n---\n\n"
143
+
144
+ # Standard optional parameters for search functions
145
+ OPTIONAL_SEARCH_PARAMS = ["page_size", "start_from", "starts_with", "ends_with", "ignore_case"]
146
+ OPTIONAL_FILTER_PARAMS = ["page_size", "start_from"]
147
+
148
+ # Define shared elements
149
+ COMMON_COLUMNS = [
150
+ Column(name='Display Name', key='display_name'),
151
+ Column(name='Qualified Name', key='qualified_name', format=False),
152
+ Column(name='Category', key='category'),
153
+ Column(name='Description', key='description', format=True),
154
+ Column(name='Type Name', key='type_name'),
155
+ Column(name='URL', key='url')
156
+ ]
157
+ # Preferred terminology alias
158
+ COMMON_ATTRIBUTES = COMMON_COLUMNS
159
+
160
+ COMMON_METADATA_COLUMNS = [
161
+ Column(name='GUID', key='guid', format=True),
162
+ Column(name='Metadata Collection ID', key='metadata_collection_id', format=True),
163
+ Column(name='Metadata Collection Name', key='metadata_collection_name', format=True),
164
+ ]
165
+
166
+ COMMON_HEADER_COLUMNS = [
167
+ Column(name="Classifications", key='classifications'),
168
+ Column(name="Created By", key='created_by'),
169
+ Column(name="Create Time", key='create_time'),
170
+ Column(name="Updated By", key='updated_by'),
171
+ Column(name="Update Time", key='update_time'),
172
+ Column(name="Effective From", key='effective_from'),
173
+ Column(name="Effective To", key='effective_to'),
174
+ Column(name="Version", key='version'),
175
+ Column(name="Open Metadata Type Name", key='type_name'),
176
+ ]
177
+
178
+ REFERNCEABLE_COLUMNS = COMMON_COLUMNS + [
179
+ Column(name='Version Identifier', key='version_identifier'),
180
+ Column(name='Additional Properties', key='additional_properties')
181
+ ]
182
+
183
+ COMMON_FORMATS_ALL = Format(
184
+ types=["ALL"],
185
+ attributes=COMMON_COLUMNS,
186
+ )
187
+
188
+ MERMAID_FORMAT = Format(
189
+ types=["MERMAID"],
190
+ attributes=[Attribute(name='Mermaid', key='mermaidGraph')]
191
+ )
192
+
193
+ EXT_REF_COLUMNS = COMMON_COLUMNS + [
194
+ Column(name='Reference Title', key='reference_title'),
195
+ Column(name='Reference Abstract', key='reference_abstract'),
196
+ Column(name='Authors', key='authors'),
197
+ Column(name='Organization', key='organization'),
198
+ Column(name='Reference URL', key='reference_url'),
199
+ Column(name='Sources', key='sources'),
200
+ Column(name='License', key='license'),
201
+ Column(name='Copyright', key='copyright'),
202
+ Column(name='Attribution', key='attribution'),
203
+ ]
204
+
205
+ PROJECT_COLUMNS = COMMON_COLUMNS + [
206
+ Column(name="Classifications", key='classifications'),
207
+ Column(name='Priority', key='priority'),
208
+ Column(name='Project Status', key='project_status'),
209
+ Column(name='Element Status', key='status'),
210
+ Column(name='Start Date', key='start_date'),
211
+ Column(name='Assigned Actors', key='assigned_actors'),
212
+ Column(name='Resources', key='resource_list'),
213
+ Column(name="Project Roles", key='project_roles'),
214
+ Column(name="Managed Projects", key='managed_projects'),
215
+ ]
216
+
217
+ GLOSSARY_COLUMNS = COMMON_COLUMNS + [
218
+ Column(name="Language", key='language'),
219
+ Column(name='Usage', key='usage'),
220
+ Column(name='Folders', key='collection_members'),
221
+ ]
222
+
223
+ COLLECTIONS_COLUMNS = COMMON_COLUMNS + [
224
+ Column(name='Classifications', key='classifications'),
225
+ Column(name="Created By", key='created_by'),
226
+ Column(name="Create Time", key='create_time'),
227
+ Column(name="Updated By", key='updated_by'),
228
+ Column(name="Update Time", key='update_time'),
229
+ ]
230
+
231
+ COLLECTIONS_MEMBERS_COLUMNS = COLLECTIONS_COLUMNS + [
232
+ Column(name="Containing Members", key='collection_members'),
233
+ Column(name="Member Of", key='member_of_collections')
234
+ ]
235
+
236
+ COLLECTION_DICT = Format(
237
+ types=["DICT"],
238
+ attributes=COLLECTIONS_MEMBERS_COLUMNS + [
239
+ Column(name="GUID", key='GUID'),
240
+ ],
241
+ )
242
+
243
+ BASIC_COLLECTIONS_COLUMNS = [
244
+ Column(name='Qualified Name', key='qualified_name', format=False),
245
+ Column(name='GUID', key='guid', format=True),
246
+ Column(name='Type Name', key='type_name'),
247
+ Column(name="Containing Members", key='collection_members'),
248
+ Column(name="Member Of", key='member_of_collections')
249
+ ]
250
+
251
+ COLLECTION_REPORT = Format(
252
+ types=["REPORT"],
253
+ attributes=COLLECTIONS_MEMBERS_COLUMNS + [
254
+ Column(name="GUID", key='GUID'),
255
+ Column(name="Mermaid", key='mermaidGraph'),
256
+ ],
257
+ )
258
+
259
+ COLLECTION_TABLE = Format(
260
+ types=["TABLE"],
261
+ attributes=COLLECTIONS_MEMBERS_COLUMNS,
262
+ )
263
+
264
+ GOVERNANCE_DEFINITIONS_COLUMNS = COMMON_COLUMNS + [
265
+ Column(name="Summary", key='summary'),
266
+ Column(name="Usage", key='usage'),
267
+ Column(name="Importance", key='importance'),
268
+ Column(name="Scope", key='scope'),
269
+ Column(name="Type", key='type_name'),
270
+ ]
271
+ GOVERNANCE_DEFINITIONS_BASIC = [
272
+ Column(name="Type", key='type_name'),
273
+ Column(name="Summary", key='summary'),
274
+ Column(name='Qualified Name', key='qualified_name', format=False),
275
+ Column(name="GUID", key='guid', format=True),
276
+ ]
277
+ COMMON_ANNOTATIONS = {
278
+ "wikilinks": ["[[Commons]]"]
279
+ }
280
+
281
+ WHO = [
282
+ "Who created this?", # header
283
+ "Who last updated this?", # header
284
+ "Who owns this?", # ownership classification
285
+ "Who has been working on this?" # header - modified_users
286
+ ]
287
+ WHAT = [
288
+ "What is this?", # description
289
+ "What is the source of this?", # metadata_collection_id/name
290
+ "What type is this?" # type
291
+ "What zone is this?" # Anchors classification - zone membership
292
+ ]
293
+
294
+ WHEN = [
295
+ "When was this created?", # create
296
+ "When was this last updated?",
297
+ "When did this become effective?",
298
+ "When will this no longer be effective?",
299
+ "Is this effective?",
300
+ "What was the value last week?",
301
+ "What was the value last month?",
302
+ "What was the value last quarter?",
303
+ "What was the value last year?"
304
+ ]
305
+
306
+ TIME_PARAMETERS = ["as_of_time", "effective_time"]
307
+
308
+ # Modularized report_specs
309
+ base_report_specs = FormatSetDict({
310
+ "Referenceable": FormatSet(
311
+ heading="Default Attributes for a Referenceable",
312
+ description="Basic attributes for a Referenceable",
313
+ annotations={}, # No specific annotations
314
+ family="General",
315
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
316
+ formats=[
317
+ Format(
318
+ types=["ALL", "TABLE", "DICT"],
319
+ attributes=COMMON_COLUMNS + [
320
+ Column(name='Version Identifier', key='version_identifier'),
321
+ Column(name="Classifications", key='classifications'),
322
+ Column(name="Additional Properties", key='additional_properties'),
323
+ Column(name="Created By", key='created_by'),
324
+ Column(name="Create Time", key='create_time'),
325
+ Column(name="Updated By", key='updated_by'),
326
+ Column(name="Update Time", key='update_time'),
327
+ Column(name="Effective From", key='effective_from'),
328
+ Column(name="Effective To", key='effective_to'),
329
+ Column(name="Version", key='version'),
330
+ Column(name="Open Metadata Type Name", key='type_name'),
331
+ Column(name="Content Status", key='content_status'),
332
+ Column(name="Activity Status", key='activity_status'),
333
+ Column(name="Deployment Status", key='deployment_status'),
334
+ ],
335
+ )
336
+ ],
337
+ action=ActionParameter(
338
+ function="ClassificationManager.get_elements_by_property_value",
339
+ optional_params=OPTIONAL_FILTER_PARAMS + ["metadata_element_type_name"] + TIME_PARAMETERS,
340
+ required_params=["property_value"],
341
+ spec_params={"property_names": ["displayName", "qualifiedName"]},
342
+ )
343
+ ),
344
+ "Default": FormatSet(
345
+ heading="Default Base Attributes",
346
+ description="Was a valid combination of report_spec and output_format provided?",
347
+ annotations={}, # No specific annotations
348
+ family="General",
349
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
350
+ formats=[
351
+ Format(
352
+ types=["ALL", "TABLE", "DICT"],
353
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
354
+ Column(name='Version Identifier', key='version_identifier'),
355
+ Column(name="Classifications", key='classifications'),
356
+ Column(name="Additional Properties", key='additional_properties'),
357
+ Column(name="Created By", key='created_by'),
358
+ Column(name="Create Time", key='create_time'),
359
+ Column(name="Updated By", key='updated_by'),
360
+ Column(name="Update Time", key='update_time'),
361
+ Column(name="Effective From", key='effective_from'),
362
+ Column(name="Effective To", key='effective_to'),
363
+ Column(name="Version", key='version'),
364
+ Column(name="Open Metadata Type Name", key='type_name'),
365
+ ],
366
+ )
367
+ ],
368
+ action=ActionParameter(
369
+ function="ClassificationManager.get_elements_by_property_value",
370
+ optional_params=OPTIONAL_FILTER_PARAMS + ["metadata_element_type_name"] + TIME_PARAMETERS,
371
+ required_params=["property_value"],
372
+ spec_params={"property_names": ["displayName", "qualifiedName"]},
373
+ )
374
+ ),
375
+ "Element-By-Owner": FormatSet(
376
+ heading="Elements by Owner",
377
+ description="Return elements for the specified owner",
378
+ annotations={}, # No specific annotations
379
+ family="General",
380
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
381
+ formats=[
382
+ Format(
383
+ types=["ALL", "TABLE", "DICT"],
384
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
385
+ Column(name='Version Identifier', key='version_identifier'),
386
+ Column(name="Classifications", key='classifications'),
387
+ Column(name="Additional Properties", key='additional_properties'),
388
+ Column(name="Created By", key='created_by'),
389
+ Column(name="Create Time", key='create_time'),
390
+ Column(name="Updated By", key='updated_by'),
391
+ Column(name="Update Time", key='update_time'),
392
+ Column(name="Effective From", key='effective_from'),
393
+ Column(name="Effective To", key='effective_to'),
394
+ Column(name="Version", key='version'),
395
+ Column(name="Open Metadata Type Name", key='type_name'),
396
+ ],
397
+ )
398
+ ],
399
+ action=ActionParameter(
400
+ function="ClassificationManager.get_owners_elements",
401
+ optional_params=['body'],
402
+ required_params=["owner_name"],
403
+ spec_params={},
404
+ )
405
+ ),
406
+ "Actor-Profiles": FormatSet(
407
+ target_type="Actor Profile",
408
+ heading="Actor Profile",
409
+ description="Actor Profile Information",
410
+ annotations={}, # No specific annotations
411
+ family="ActorManager",
412
+ formats=[
413
+ Format(
414
+ types=["ALL"],
415
+ attributes=COMMON_COLUMNS + [
416
+ Column(name="Open Metadata Type Name", key='type_name'),
417
+ Column(name="GUID", key='GUID'),
418
+ ],
419
+ )
420
+ ],
421
+ action=ActionParameter(
422
+ function="ActorManager.find_actor_profiles",
423
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
424
+ required_params=["search_string"],
425
+ spec_params={},
426
+ )
427
+ ),
428
+ "Actor-Roles": FormatSet(
429
+ target_type="Actor Profile",
430
+ heading="Actor Profile",
431
+ description="Actor Profile Information",
432
+ annotations={}, # No specific annotations
433
+ family="ActorManager",
434
+ formats=[
435
+ Format(
436
+ types=["ALL"],
437
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
438
+ Column(name="Scope", key='scope'),
439
+ ],
440
+ )
441
+ ],
442
+ action=ActionParameter(
443
+ function="ActorManager.find_actor_roles",
444
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
445
+ required_params=["search_string"],
446
+ spec_params={},
447
+ )
448
+ ),
449
+
450
+ "User-Identities": FormatSet(
451
+ target_type="User-Identity",
452
+ heading="User Identity Information",
453
+ description="User Identity Information",
454
+ annotations={}, # No specific annotations
455
+ family="ActorManager",
456
+ formats=[
457
+ Format(
458
+ types=["ALL"],
459
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
460
+ Column(name="User ID", key='user_id'),
461
+ Column(name="Distinguished Name", key='distinguished_name')
462
+ ],
463
+ )
464
+ ],
465
+ action=ActionParameter(
466
+ function="ActorManager.find_user_identities",
467
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
468
+ required_params=["search_string"],
469
+ spec_params={},
470
+ )
471
+ ),
472
+
473
+ "TypeDef": FormatSet(
474
+ target_type="TypeDef",
475
+ heading="TypeDef",
476
+ description="Attributes that describe TypeDefs",
477
+ annotations={}, # No specific annotations
478
+ family="TypeDef",
479
+ formats=[
480
+ Format(
481
+ types=["ALL"],
482
+ attributes=[
483
+ Column(name='Type Name', key='name'),
484
+ Column(name="Category", key='category'),
485
+ Column(name="Description", key='description'),
486
+ Column(name="Bean Class", key='beanClassName'),
487
+ Column(name="Initial Status", key='initialStatus'),
488
+ Column(name="Description Wiki", key='descriptionWiki'),
489
+
490
+ ],
491
+ )
492
+ ],
493
+ ),
494
+
495
+ "Valid-Values": FormatSet(
496
+ target_type="Valid-Values",
497
+ heading="Valid Values",
498
+ description="Attributes that describe valid values",
499
+ annotations={}, # No specific annotations
500
+ family="Valid-Values",
501
+ formats=[
502
+ Format(
503
+ types=["ALL"],
504
+ attributes=[
505
+ Column(name='Name', key='display_name'),
506
+ Column(name="Category", key='category'),
507
+ Column(name="Property Name", key='property_name'),
508
+ Column(name="Description", key='description'),
509
+ Column(name="Preferred Value", key='preferred_value'),
510
+ Column(name="Data Type", key='dataType'),
511
+ Column(name="Is Case Sensitive", key='is_case_sensitive'),
512
+ Column(name="Additional Properties", key='additional_properties'),
513
+
514
+ ],
515
+ )
516
+ ],
517
+ action=ActionParameter(
518
+ function="ValidValueManager.find_valid_values",
519
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS + ["type_name"],
520
+ required_params=["property_name"],
521
+ spec_params={},
522
+ )
523
+ ),
524
+
525
+ "Engine-Actions": FormatSet(
526
+ target_type="Referenceable",
527
+ heading="Engine Actions",
528
+ description="A Display of Engine Actions",
529
+ annotations={}, # No specific annotations
530
+ family="AutomatedCuration",
531
+ formats=[
532
+ Format(
533
+ types=["ALL"],
534
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
535
+ Column(name='Version Identifier', key='version_identifier'),
536
+ Column(name="Classifications", key='classifications'),
537
+ Column(name="Additional Properties", key='additional_properties'),
538
+ Column(name="Created By", key='created_by'),
539
+ Column(name="Create Time", key='create_time'),
540
+ Column(name="Updated By", key='updated_by'),
541
+ Column(name="Update Time", key='update_time'),
542
+ Column(name="Effective From", key='effective_from'),
543
+ Column(name="Effective To", key='effective_to'),
544
+ Column(name="Version", key='version'),
545
+ Column(name="Open Metadata Type Name", key='type_name'),
546
+ ],
547
+ )
548
+ ],
549
+ ),
550
+ "Asset-Graph": FormatSet(
551
+ target_type="Asset",
552
+ heading="Asset Graph",
553
+ description="Attributes that apply to all Assets",
554
+ annotations={}, # No specific annotations
555
+ family="AssetCatalog",
556
+ formats=[
557
+ Format(
558
+ types=["ALL"],
559
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
560
+ Column(name="Classifications", key='classifications'),
561
+ Column(name="Created By", key='created_by'),
562
+ Column(name="Create Time", key='create_time'),
563
+ Column(name="Updated By", key='updated_by'),
564
+ Column(name="Update Time", key='update_time'),
565
+ Column(name="Version", key='version'),
566
+ Column(name="Open Metadata Type Name", key='type_name'),
567
+ Column(name="Mermaid Graph", key='mermaidGraph'),
568
+ Column(name="Anchor Graph", key='anchorMermaidGRaph'),
569
+ Column(name="Field Level Lineage Graph", key='fieldLevelLineageGraph'),
570
+ ],
571
+ )
572
+ ],
573
+ action=ActionParameter(
574
+ function="ServerClient.get_asset_graph",
575
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
576
+ required_params=["asset_guid"],
577
+ spec_params={},
578
+ )
579
+ ),
580
+ "Common-Mermaid": FormatSet(
581
+ target_type="Referenceable",
582
+ heading="Common Attributes with Mermaid",
583
+ description="Common Attributes and all Mermaid graphs.",
584
+ annotations={}, # No specific annotations
585
+ family="General",
586
+ formats=[
587
+ Format(
588
+ types=["DICT", "REPORT"],
589
+ attributes=[
590
+ Column(name='Display Name', key='display_name'),
591
+ Column(name="Qualified Name", key='qualified_name'),
592
+ Column(name="Description", key='description'),
593
+ Column(name="GUID", key='guid'),
594
+ Column(name="Mermaid Graph", key='mermaidGraph'),
595
+ Column(name="Anchor Mermaid Graph", key='anchorMermaidGraph'),
596
+ Column(name="Information Supply Chain Mermaid Graph", key='informationSupplyChainMermaidGraph'),
597
+ Column(name="Field Level Lineage Graph", key='fieldLevelLineageGraph'),
598
+ Column(name="Action Mermaid Graph", key='actionMermaidGraph'),
599
+ Column(name="Local Lineage Graph", key="localLineageGraph"),
600
+ Column(name="Edge Mermaid", key="edgeMermaidGraph"),
601
+ Column(name="ISC Implementation Graph", key='iscImplementationGraph'),
602
+ Column(name="Specification Mermaid Graph", key='specificationMermaidGraph'),
603
+ Column(name="Solution Blueprint Mermaid Graph", key='solutionBlueprintMermaidGraph'),
604
+ Column(name="Solution Subcomponent Mermaid Graph", key='solutionSubcomponentMermaidGraph'),
605
+
606
+ ],
607
+ ),
608
+ Format(
609
+ types=["MERMAID"],
610
+ attributes=[
611
+ Column(name="Mermaid Graph", key='mermaidGraph')
612
+ ])
613
+ ],
614
+
615
+ ),
616
+ "Tech-Type-Elements": FormatSet(
617
+ target_type="TechTypeElements",
618
+ heading="Technology Type Elements",
619
+ description="Elements of a Technology",
620
+ annotations={}, # No specific annotations
621
+ family="Automated Curation",
622
+ formats=[
623
+ Format(
624
+ types=["MD", "FORM", ],
625
+ attributes=COMMON_HEADER_COLUMNS + [
626
+ Column(name='Display Name', key='display_name'),
627
+ Column(name="Qualified Name", key='qualified_name'),
628
+ Column(name="GUID", key='guid', format=True),
629
+ Column(name="Description", key='description'),
630
+ Column(name='Metadata Collection Name', key='metadata_collection_name', format=True),
631
+ Column(name="Deployed Implementation", key='deployedImplementationType'),
632
+ Column(name="Mermaid Graph", key='mermaidGraph'),
633
+ Column(name="Specification Mermaid Graph", key='specificationMermaidGraph')
634
+ ],
635
+ ),
636
+ Format(
637
+ types=["MERMAID", "HTML", "REPORT"],
638
+ attributes=COMMON_HEADER_COLUMNS + [
639
+ Column(name='Display Name', key='display_name'),
640
+ Column(name="Qualified Name", key='qualified_name'),
641
+ Column(name="GUID", key='guid', Format=True),
642
+ Column(name="Description", key='description'),
643
+ Column(name="Deployed Implementation", key='deployedImplementationType'),
644
+ Column(name="Mermaid Graph", key='mermaidGraph'),
645
+ Column(name="Specification Mermaid Graph", key='specificationMermaidGraph')
646
+ ]
647
+ ),
648
+ Format(
649
+ types=["DICT", "TABLE", "LIST"],
650
+ attributes=[
651
+ Column(name='Display Name', key='display_name'),
652
+ Column(name="Qualified Name", key='qualified_name'),
653
+ Column(name="GUID", key='guid', Format=True),
654
+ Column(name="Description", key='description'),
655
+ Column(name="Deployed Implementation", key='deployedImplementationType'),
656
+ ]
657
+ )
658
+ ],
659
+ action=ActionParameter(
660
+ function="EgeriaTech.get_technology_type_elements",
661
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS + ["get_templates"],
662
+ required_params=["filter"],
663
+ spec_params={},
664
+ )
665
+ ),
666
+ "Search-Keywords": FormatSet(
667
+ heading="Search Keyword Report",
668
+ description="A report of elements with search keywords matching the specified string",
669
+ annotations={}, # No specific annotations
670
+ family="Feedback Manager",
671
+ formats=[
672
+ Format(
673
+ types=["ALL"],
674
+ attributes=[
675
+ Column(name='Search Keyword', key='keyword'),
676
+ Column(name="Search Keyword GUID", key='guid'),
677
+ Column(name="Element Display Name", key='element_display_name'),
678
+ Column(name="Element GUID", key='element_guid'),
679
+ Column(name="Element Type", key='element_type'),
680
+ Column(name="Element Description", key='element_description'),
681
+ Column(name="Element Category", key='element_category'),
682
+ ],
683
+ )
684
+ ],
685
+ action=ActionParameter(
686
+ function="_client_new.find_search_keywords",
687
+ optional_params=OPTIONAL_SEARCH_PARAMS,
688
+ required_params=["search_string"],
689
+ spec_params={},
690
+ ),
691
+ get_additional_props=ActionParameter(
692
+ function="_client_extract_element_properties_for_keyword",
693
+ required_params=[],
694
+ spec_params={},
695
+ )
696
+ ),
697
+ "Tech-Type-Details": FormatSet(
698
+ target_type="TechTypeDetail",
699
+ heading="Technology Type Details",
700
+ description="Details of a Technology Type Valid Value.",
701
+ annotations={}, # No specific annotations
702
+ family="Automated Curation",
703
+ formats=[
704
+ Format(
705
+ types=["ALL"],
706
+ attributes=[
707
+ Column(name='Display Name', key='display_name'),
708
+ Column(name="Qualified Name", key='qualified_name'),
709
+ Column(name="GUID", key='guid'),
710
+ Column(name="Description", key='description'),
711
+ Column(name="Catalog Template Placeholders", key='catalog_template_specs'),
712
+ ],
713
+ )
714
+ ],
715
+ action=ActionParameter(
716
+ function="ServerClient.get_tech_type_detail",
717
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
718
+ required_params=["filter"],
719
+ spec_params={},
720
+ )
721
+ ),
722
+ "Tech-Type-Processes": FormatSet(
723
+ target_type="TechTypeDetail",
724
+ heading="Technology Type Processes",
725
+ description="Governance Processes for a Tech Type",
726
+ annotations={}, # No specific annotations
727
+ family="Automated Curation",
728
+ formats=[
729
+ Format(
730
+ types=["REPORT", "LIST", "FORM", "MD", "TABLE"],
731
+ attributes=[
732
+ Column(name='Display Name', key='display_name'),
733
+ Column(name="Qualified Name", key='qualified_name'),
734
+ Column(name="Governance Processes", key='governance_processes'),
735
+ ],
736
+ ),
737
+ Format(
738
+ types=["DICT"],
739
+ attributes=[
740
+ Column(name='Display Name', key='display_name'),
741
+ Column(name="Qualified Name", key='qualified_name'),
742
+ Column(name="Governance Processes", key='governance_processes_d'),
743
+ Column(name="Mermaid", key='mermaidGraph'),
744
+ Column(name="Mermaid Specification", key='specificationMermaidGraph'),
745
+ ],
746
+ ),
747
+ Format(
748
+ types=["MERMAID"],
749
+ attributes=[
750
+ Column(name="Mermaid", key='mermaidGraph'),
751
+ Column(name="Mermaid Specification", key='specificationMermaidGraph'),
752
+ ],
753
+ )
754
+ ],
755
+ action=ActionParameter(
756
+ function="ServerClient.get_tech_type_detail",
757
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
758
+ required_params=["filter"],
759
+ spec_params={},
760
+ )
761
+ ),
762
+ "Tech-Types": FormatSet(
763
+ target_type="TechTypeDetail",
764
+ heading="Technology Type Details",
765
+ description="Details of a Technology Type Valid Value.",
766
+ annotations={}, # No specific annotations
767
+ family="Automated Curation",
768
+ formats=[
769
+ Format(
770
+ types=["ALL"],
771
+ attributes=[
772
+ Column(name='Display Name', key='display_name'),
773
+ Column(name="Qualified Name", key='qualified_name'),
774
+ Column(name="GUID", key='guid'),
775
+ Column(name="Description", key='description'),
776
+ Column(name="Reference URL", key='url'),
777
+ ],
778
+ )
779
+ ],
780
+ action=ActionParameter(
781
+ function="ServerClient.find_technology_types",
782
+ optional_params=OPTIONAL_SEARCH_PARAMS,
783
+ required_params=["search_string"],
784
+ spec_params={},
785
+ )
786
+ ),
787
+ "Platforms": FormatSet(
788
+ target_type="Platform",
789
+ heading="OMAG Server Platform",
790
+ description="Details of an OMAG Server Platform",
791
+ annotations={},
792
+ family="RuntimeManager",
793
+ formats=[
794
+ Format(
795
+ types=["ALL", "TABLE", "DICT"],
796
+ attributes=COMMON_COLUMNS + [
797
+ Column(name="GUID", key='guid'),
798
+ Column(name="Platform URL", key='platform_url_root'),
799
+ Column(name="Platform Version", key='version'),
800
+ Column(name="Platform Origin", key='platform_origin'),
801
+ Column(name="Platform Start Time", key='platform_start_time'),
802
+ Column(name="Build Properties", key="platform_build_properties"),
803
+ Column(name="Servers", key="omag_servers"),
804
+ ],
805
+ )
806
+ ],
807
+ ),
808
+ "OMAGServers": FormatSet(
809
+ target_type="OMAGServer",
810
+ heading="OMAG Server",
811
+ description="Details of an OMAG Server",
812
+ annotations={},
813
+ family="RuntimeManager",
814
+ formats=[
815
+ Format(
816
+ types=["ALL", "TABLE", "DICT"],
817
+ attributes=COMMON_COLUMNS + [
818
+ Column(name="GUID", key='guid'),
819
+ Column(name="Server Name", key='server_name'),
820
+ Column(name="Server Type", key='server_type'),
821
+ Column(name="Server Status", key='server_active_status'),
822
+ Column(name="Server Config", key='server_configuration'),
823
+ ],
824
+ )
825
+ ],
826
+ ),
827
+ "IntegrationConnectors": FormatSet(
828
+ target_type="IntegrationConnector",
829
+ heading="Integration Connector",
830
+ description="Details of an Integration Connector",
831
+ annotations={},
832
+ family="RuntimeManager",
833
+ formats=[
834
+ Format(
835
+ types=["ALL", "TABLE", "DICT"],
836
+ attributes=COMMON_COLUMNS + [
837
+ Column(name="GUID", key='guid'),
838
+ Column(name="Connector Name", key='connector_name'),
839
+ Column(name="Connector Type", key='connector_type'),
840
+ Column(name="Metadata Source", key='metadata_source_qualified_name'),
841
+ Column(name="Status", key='status'),
842
+ Column(name="Last Status Change", key='last_status_change'),
843
+ ],
844
+ )
845
+ ],
846
+ ),
847
+
848
+ "Journal-Entry-DrE": FormatSet(
849
+ target_type="Notification",
850
+ heading="Journal Entry",
851
+ description="Details of a journal entry.",
852
+ annotations={}, # No specific annotations
853
+ family="Feedback Manager",
854
+ formats=[
855
+ Format(
856
+ types=["ALL"],
857
+ attributes=[
858
+ Column(name='Journal Name', key='note_log_name'),
859
+ Column(name='Journal Qualified Name', key='note_log_qualified_name'),
860
+ Column(name="Journal Entry Qualified Name", key='qualified_name'),
861
+ Column(name="Journal Entry GUID", key='guid'),
862
+ Column(name="Journal Entry", key='description')
863
+ ],
864
+ )
865
+ ],
866
+ action=ActionParameter(
867
+ function="ServerClient.find_notes",
868
+ optional_params=OPTIONAL_SEARCH_PARAMS,
869
+ required_params=["search_string"],
870
+ spec_params={},
871
+ )
872
+ ),
873
+ "Informal-Tags-DrE": FormatSet(
874
+ target_type="Informal Tag",
875
+ heading="Informal Tags",
876
+ description="Details of Informal Tags.",
877
+ annotations={}, # No specific annotations
878
+ family="Feedback Manager",
879
+ formats=[
880
+ Format(
881
+ types=["ALL"],
882
+ attributes=[
883
+ Column(name='Tag Name', key='display_name'),
884
+ Column(name='Qualified Name', key='qualified_name'),
885
+ Column(name="Description", key='description'),
886
+ Column(name="GUID", key='guid'),
887
+ Column(name="Tagged Elements", key='tagged_elements'),
888
+ ],
889
+ )
890
+ ],
891
+ action=ActionParameter(
892
+ function="ServerClient.find_tags",
893
+ optional_params=OPTIONAL_SEARCH_PARAMS,
894
+ required_params=["search_string"],
895
+ spec_params={},
896
+ )
897
+ ),
898
+
899
+ "ExternalReference": FormatSet(
900
+ target_type="External Reference",
901
+ heading="External Reference Attributes",
902
+ description="Attributes that apply to all External References.",
903
+ annotations={},
904
+ family="External References",
905
+ aliases=["ExternalDataSource", "ExternalModelSource", "External References"],
906
+ formats=[
907
+ Format(
908
+ types=["ALL"],
909
+ attributes=EXT_REF_COLUMNS,
910
+ )
911
+ ],
912
+ action=ActionParameter(
913
+ function="ExternalReference.find_external_references",
914
+ optional_params=OPTIONAL_SEARCH_PARAMS,
915
+ required_params=["search_string"],
916
+ spec_params={},
917
+ )
918
+ ),
919
+ "RelatedMedia": FormatSet(
920
+ target_type="Related Media",
921
+ heading="Related Media Attributes",
922
+ description="Attributes that apply to related media.",
923
+ annotations={},
924
+ family="External References",
925
+ formats=[
926
+ Format(
927
+ types=["ALL", "LIST"],
928
+ attributes=EXT_REF_COLUMNS + [
929
+ Column(name="Media Type", key='media_type'),
930
+ Column(name="Media Type Other Id", key='media_type_other_id'),
931
+ Column(name="Default Media Usage", key='default_media_usage'),
932
+ Column(name="Default Media Usage Other Id", key='default_media_usage_other_id')
933
+ ],
934
+ )
935
+ ],
936
+ action=ActionParameter(
937
+ function="ExternalReference.find_external_references",
938
+ optional_params=OPTIONAL_SEARCH_PARAMS,
939
+ required_params=["search_string"],
940
+ spec_params={"metadata_element_subtypes": ["RelatedMedia"]},
941
+ )
942
+
943
+ ),
944
+ "CitedDocument": FormatSet(
945
+ target_type="Cited Document",
946
+ heading="Cited Document Attributes",
947
+ description="Attributes that apply to all Cited Documents.",
948
+ annotations={},
949
+ family="External References",
950
+ formats=[
951
+ Format(
952
+ types=["ALL", "LIST"],
953
+ attributes=EXT_REF_COLUMNS + [
954
+ Column(name="Number of Pages", key='number_of_pages'),
955
+ Column(name="Page Range", key='page_range'),
956
+ Column(name="Publication Series", key='publication_series'),
957
+ Column(name="Publication Series Volume", key='publication_series_volume'),
958
+ Column(name="Publisher", key='publisher'),
959
+ Column(name="Edition", key='edition'),
960
+ Column(name="First Publication Date", key='first_publication_date'),
961
+ Column(name="Publication Date", key='publication_date'),
962
+ Column(name="Publication City", key='publication_city'),
963
+ Column(name="Publication Year", key='publication_year'),
964
+ Column(name="Publication Numbers", key='publication_numbers'),
965
+ ],
966
+ )
967
+ ],
968
+ action=ActionParameter(
969
+ function="ExternalReference.find_external_references",
970
+ optional_params=OPTIONAL_SEARCH_PARAMS,
971
+ required_params=["search_string"],
972
+ spec_params={"metadata_element_subtypes": ["CitedDocument"]},
973
+ )
974
+
975
+ ),
976
+ "Projects": FormatSet(
977
+ target_type="Project",
978
+ heading="Project Attributes",
979
+ description="Attributes that apply to all Projects.",
980
+ annotations={},
981
+ family="Project Manager",
982
+ formats=[
983
+ Format(
984
+ types=["ALL", "LIST"],
985
+ attributes=PROJECT_COLUMNS
986
+ )
987
+ ],
988
+ action=ActionParameter(
989
+ function="ProjectManager.find_projects",
990
+ optional_params=OPTIONAL_SEARCH_PARAMS,
991
+ required_params=["search_string"],
992
+ spec_params={},
993
+ )
994
+
995
+ ),
996
+ "Glossaries": FormatSet(
997
+ target_type="Glossary",
998
+ heading="Glossary Attributes",
999
+ description="Attributes that apply to all Glossaries.",
1000
+ annotations={"wikilinks": ["[[Glossaries]]"]},
1001
+ family="Glossary Manager",
1002
+ formats=[
1003
+ Format(
1004
+ types=["ALL"],
1005
+ attributes=GLOSSARY_COLUMNS
1006
+ )
1007
+ ],
1008
+ action=ActionParameter(
1009
+ function="GlossaryManager.find_glossaries",
1010
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1011
+ required_params=["search_string"],
1012
+ spec_params={},
1013
+ )
1014
+ ),
1015
+ "Glossary-Terms": FormatSet(
1016
+ target_type="Term",
1017
+ # aliases=["Glossary-Terms"],
1018
+ heading="Basic Glossary Term Attributes",
1019
+ description="Attributes that apply to all Basic Glossary Terms.",
1020
+ annotations={},
1021
+ family="Glossary Manager",
1022
+ formats=[
1023
+ Format(
1024
+ types=["ALL"],
1025
+ attributes=COMMON_COLUMNS + COMMON_METADATA_COLUMNS + [
1026
+ Column(name='Version Identifier', key='version_identifier'),
1027
+ Column(name="Summary", key='summary'),
1028
+ Column(name="Additional Properties", key='additional_properties'),
1029
+ Column(name="Example", key='example'),
1030
+ Column(name="Usage", key='usage'),
1031
+ Column(name="Updated By", key='updated_by'),
1032
+ Column(name="Update Time", key='update_time'),
1033
+ Column(name="Effective From", key='effective_from'),
1034
+ Column(name="Effective To", key='effective_to'),
1035
+ Column(name="GUID", key='guid'),
1036
+ Column(name="Open Metadata Type Name", key='type_name'),
1037
+ Column(name="Glossary", key='parent_glossary'),
1038
+ Column(name="Subject Area", key='subject_area'),
1039
+ ],
1040
+ )
1041
+ ],
1042
+ action=ActionParameter(
1043
+ function="GlossaryManager.find_glossary_terms",
1044
+ required_params=["search_string"],
1045
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1046
+ spec_params={},
1047
+ )
1048
+ ),
1049
+ "Help-Terms": FormatSet(
1050
+ target_type="Term",
1051
+ heading="Display Help for Dr.Egeria Commands",
1052
+ description="Designed for help output of Dr.Egeria commands.",
1053
+ annotations={"wikilinks": ["[[Help]]", "[[Dr.Egeria]]"]},
1054
+ family="General",
1055
+ formats=[
1056
+ Format(
1057
+
1058
+ types=["DICT", "FORM", "REPORT", "LIST", "TABLE"],
1059
+ attributes=[
1060
+ Column(name='Term Name', key='display_name'),
1061
+ Column(name='Description', key='description'),
1062
+ Column(name="Usage", key='usage', format=True),
1063
+ Column(name="Update Time", key='update_time')
1064
+
1065
+ ],
1066
+ )
1067
+ ],
1068
+ action=ActionParameter(
1069
+ function="GlossaryManager.find_glossary_terms",
1070
+ required_params=["search_string"],
1071
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1072
+ spec_params={},
1073
+ )
1074
+ ),
1075
+
1076
+ "Collections": FormatSet(
1077
+ target_type="Collection",
1078
+ heading="Common Collection Information",
1079
+ description="Attributes generic to all Collections.",
1080
+ aliases=["Collection", "RootCollection", "Folder", "ReferenceList", "HomeCollection",
1081
+ "ResultSet", "RecentAccess", "WorkItemList", "Namespace"],
1082
+ annotations=COMMON_ANNOTATIONS,
1083
+ family="Collection Manager",
1084
+ formats=[MERMAID_FORMAT, COLLECTION_DICT, COLLECTION_TABLE, COLLECTION_REPORT, COMMON_FORMATS_ALL],
1085
+ # Reusing common formats
1086
+ action=ActionParameter(
1087
+ function="CollectionManager.find_collections",
1088
+ required_params=["search_string"],
1089
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1090
+ spec_params={},
1091
+ )
1092
+ ),
1093
+ "BasicCollections": FormatSet(
1094
+ target_type="Collection",
1095
+ heading="Common Collection Information",
1096
+ description="Attributes generic to all Collections.",
1097
+ aliases=[],
1098
+ annotations=COMMON_ANNOTATIONS,
1099
+ family="Collection Manager",
1100
+ formats=[Format(
1101
+ types=["ALL"],
1102
+ attributes=BASIC_COLLECTIONS_COLUMNS,
1103
+ )], # Reusing common formats
1104
+ action=ActionParameter(
1105
+ function="CollectionManager.find_collections",
1106
+ required_params=["search_string"],
1107
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1108
+ spec_params={},
1109
+ )
1110
+ ),
1111
+ "Folders": FormatSet(
1112
+ target_type="Folder",
1113
+ heading="Common Folder Information",
1114
+ description="Attributes generic to all Folders.",
1115
+ aliases=[],
1116
+ annotations=COMMON_ANNOTATIONS,
1117
+ family="External References",
1118
+ formats=[Format(
1119
+ types=["ALL"],
1120
+ attributes=BASIC_COLLECTIONS_COLUMNS,
1121
+ )], # Reusing common formats
1122
+ action=ActionParameter(
1123
+ function="CollectionManager.find_collections",
1124
+ required_params=["search_string"],
1125
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1126
+ spec_params={"metadata_element_typs": ["FolderCollection"]},
1127
+ )
1128
+ ),
1129
+
1130
+ "Collection Members": FormatSet(
1131
+ target_type="Collection",
1132
+ heading="Collection Membership Information",
1133
+ description="Attributes about all CollectionMembers.",
1134
+ aliases=["CollectionMember", "Member", "Members"],
1135
+ annotations={"wikilinks": ["[[CollectionMembers]]"]},
1136
+ family="External References",
1137
+ formats=[COLLECTION_DICT, COLLECTION_TABLE],
1138
+ action=ActionParameter(
1139
+ function="CollectionManager.get_collection_members",
1140
+ required_params=["collection_guid"],
1141
+ optional_params=OPTIONAL_FILTER_PARAMS + TIME_PARAMETERS,
1142
+ spec_params={"output_format": "DICT"},
1143
+ )
1144
+ ),
1145
+ "Solution-Blueprint": FormatSet(
1146
+ target_type="SolutionBlueprint",
1147
+ heading="Solution Blueprint Report",
1148
+ description="Details of a Solution Blueprint.",
1149
+ aliases=[],
1150
+ annotations={"Wikilinks": ["[[Solution-Blueprint]]"]},
1151
+ family="Solution Architect",
1152
+ formats=[
1153
+ Format(
1154
+ types=["DICT", "TABLE", "LIST", "MD", "FORM"],
1155
+ attributes=COLLECTIONS_MEMBERS_COLUMNS
1156
+ ),
1157
+ Format(
1158
+ types=["REPORT", "HTML"],
1159
+ attributes=COLLECTIONS_MEMBERS_COLUMNS + [
1160
+ Column(name="GUID", key='GUID'),
1161
+ Column(name="Mermaid", key='mermaidGraph'),
1162
+ Column(name="Solution Blueprint Mermaid Graph", key='solutionBlueprintMermaidGraph'),
1163
+ ]),
1164
+ Format(
1165
+ types=["MERMAID"],
1166
+ attributes=[
1167
+ Column(name="Mermaid", key='mermaidGraph'),
1168
+ Column(name="Solution Blueprint Mermaid Graph", key='solutionBlueprintMermaidGraph'),
1169
+ ])
1170
+ ],
1171
+ action=ActionParameter(
1172
+ function="SolutionArchitect.find_solution_blueprints",
1173
+ required_params=["search_string"],
1174
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1175
+ spec_params={},
1176
+ ),
1177
+ ),
1178
+ "Registered-Services": FormatSet(
1179
+ target_type="Registered-Services",
1180
+ heading="Registered Services",
1181
+ description="Registered services on the OMAG Server Platform.",
1182
+ annotations={},
1183
+ family="Platform",
1184
+ formats=[
1185
+ Format(
1186
+ types=["ALL"],
1187
+ attributes=[
1188
+ Column(name="Service Name", key='service_name'),
1189
+ Column(name="Description", key='service_description'),
1190
+ Column(name="URL Marker", key='service_url_marker'),
1191
+ Column(name="Service Type", key='service_type'),
1192
+ Column(name="Wiki", key='service_wiki'),
1193
+ Column(name="Conformance Profile", key='conformance_profile'),
1194
+ ],
1195
+ )
1196
+ ],
1197
+ ),
1198
+ "Severity-Definitions": FormatSet(
1199
+ target_type="Severity-Definitions",
1200
+ heading="Audit Log Severity Definitions",
1201
+ description="Severity definitions available in the OMAG Server.",
1202
+ annotations={},
1203
+ family="Platform",
1204
+ formats=[
1205
+ Format(
1206
+ types=["ALL"],
1207
+ attributes=[
1208
+ Column(name="Name", key='name'),
1209
+ Column(name="Ordinal", key='ordinal'),
1210
+ Column(name="Description", key='description'),
1211
+ Column(name="Severity Code", key='severity_code'),
1212
+ Column(name="System Action", key='system_action'),
1213
+ Column(name="User Action", key='user_action'),
1214
+ ],
1215
+ )
1216
+ ],
1217
+ ),
1218
+ "Asset-Types": FormatSet(
1219
+ target_type="Asset-Types",
1220
+ heading="Asset Types",
1221
+ description="Types of assets available in the catalog.",
1222
+ annotations={},
1223
+ family="AssetCatalog",
1224
+ formats=[
1225
+ Format(
1226
+ types=["ALL"],
1227
+ attributes=[
1228
+ Column(name="Type Name", key='type_name'),
1229
+ Column(name="Display Name", key='display_name'),
1230
+ Column(name="Description", key='description'),
1231
+ Column(name="Super Type", key='super_type'),
1232
+ ],
1233
+ )
1234
+ ],
1235
+ ),
1236
+ "Digital-Product-Catalog": FormatSet(
1237
+ target_type="DigitalProductCatalog",
1238
+ heading="Catalogs for Digital Products",
1239
+ description="Attributes generic to all Digital Product Catalogs..",
1240
+ aliases=["Product Catalog", "DataProductCatalog"],
1241
+ annotations={"Wikilinks": ["[[Digital Products]]"]},
1242
+ family="Product Manager",
1243
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
1244
+ formats=[
1245
+ Format(
1246
+ types=["DICT", "TABLE", "LIST", "MD", "FORM"],
1247
+ attributes=COLLECTIONS_MEMBERS_COLUMNS
1248
+ ),
1249
+ Format(
1250
+ types=["REPORT", "HTML"],
1251
+ attributes=COLLECTIONS_MEMBERS_COLUMNS + [
1252
+ Column(name="GUID", key='GUID'),
1253
+ Column(name="Mermaid", key='mermaidGraph'),
1254
+ ]),
1255
+ Format(
1256
+ types=["MERMAID"],
1257
+ attributes=[
1258
+ Column(name="Mermaid", key='mermaidGraph'),
1259
+ ])
1260
+ ],
1261
+ action=ActionParameter(
1262
+ function="CollectionManager.find_collections",
1263
+ required_params=["search_string"],
1264
+ optional_params=OPTIONAL_SEARCH_PARAMS + ['body'],
1265
+ spec_params={"metadata_element_subtypes": ["DigitalProductCatalog"],"_type":"DigitalProductCatalog"},
1266
+ ),
1267
+ ),
1268
+ "Digital-Product-Catalog-MyE": FormatSet(
1269
+ target_type="DigitalProductCatalog",
1270
+ heading="Catalogs for Digital Products",
1271
+ description="Attributes generic to all Digital Product Catalogs..",
1272
+ aliases=[],
1273
+ annotations={},
1274
+ family="Product Manager",
1275
+ formats=[
1276
+ Format(
1277
+ types=["DICT", "TABLE", "LIST", "MD", "FORM", "REPORT"],
1278
+ attributes=COMMON_COLUMNS + [
1279
+ Column(name="Containing Members", key='collection_members'),
1280
+ Column(name="Member Of", key='member_of_collections')
1281
+ ]
1282
+ ),
1283
+
1284
+ ],
1285
+ action=ActionParameter(
1286
+ function="CollectionManager.find_collections",
1287
+ required_params=["search_string"],
1288
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1289
+ spec_params={"metadata_element_subtypes": ["DigitalProductCatalog"], "_type":"DigitalProductCatalog"},
1290
+ ),
1291
+ ),
1292
+
1293
+ "Digital-Products": FormatSet(
1294
+ target_type="DigitalProduct",
1295
+ heading="Digital Product Information",
1296
+ description="Attributes useful to Digital Products.",
1297
+ aliases=["DigitalProduct", "DataProducts"],
1298
+ annotations={},
1299
+ family="Product Manager",
1300
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
1301
+ formats=[
1302
+ Format(
1303
+ types=["FORM", "DICT", "TABLE", "LIST"],
1304
+ attributes=COMMON_COLUMNS + [
1305
+ Column(name="Status", key='status'),
1306
+ Column(name='Product Name', key='product_name'),
1307
+ Column(name='Identifier', key='identifier'),
1308
+ Column(name='Maturity', key='maturity'),
1309
+ Column(name='Service Life', key='service_life'),
1310
+ Column(name='Next Version', key='next_version'),
1311
+ Column(name='Withdraw Date', key='withdraw_date'),
1312
+ Column(name='Members', key='members', format=True),
1313
+ Column(name='Uses Products', key='uses_digital_products'),
1314
+ Column(name='Used by Products', key='used_by_digital_products'),
1315
+ Column(name='Product Manager', key='assigned_actors'),
1316
+ Column(name='License', key='governed_by'),
1317
+ Column(name='Solution Blueprint', key='solution_designs'),
1318
+ ]),
1319
+ Format(
1320
+ types=["REPORT", "HTML"],
1321
+ attributes=COMMON_COLUMNS + [
1322
+ Column(name="Status", key='status'),
1323
+ Column(name='Product Name', key='product_name'),
1324
+ Column(name='Identifier', key='identifier'),
1325
+ Column(name='Maturity', key='maturity'),
1326
+ Column(name='Service Life', key='service_life'),
1327
+ Column(name='Next Version', key='next_version'),
1328
+ Column(name='Withdraw Date', key='withdraw_date'),
1329
+ Column(name='Members', key='members', format=True),
1330
+ Column(name='Uses Products', key='uses_digital_products'),
1331
+ Column(name='Used by Products', key='used_by_digital_products'),
1332
+ Column(name='Product Manager', key='assigned_actors'),
1333
+ Column(name='License', key='governed_by'),
1334
+ Column(name='Solution Blueprint', key='solution_designs'),
1335
+ Column(name="Mermaid", key="mermaid")
1336
+ ],
1337
+ )
1338
+ ],
1339
+ action=ActionParameter(
1340
+ function="CollectionManager.find_collections",
1341
+ required_params=["search_string"],
1342
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1343
+ spec_params={"metadata_element_subtypes": ["DigitalProduct"], "_type":"DigitalProduct"},
1344
+ ),
1345
+ get_additional_props=ActionParameter(
1346
+ function="CollectionManager._extract_digital_product_properties",
1347
+ required_params=[],
1348
+ spec_params={},
1349
+ )
1350
+ ),
1351
+ "Digital-Products-MyE": FormatSet(
1352
+ target_type="DigitalProduct",
1353
+ heading="Digital Product Information",
1354
+ description="Attributes useful to Digital Products.",
1355
+ aliases=[],
1356
+ annotations={},
1357
+ family="Product Manager",
1358
+ formats=[
1359
+ Format(
1360
+ types=["FORM", "DICT", "TABLE", "LIST", "MD"],
1361
+ attributes=COMMON_COLUMNS + [
1362
+ Column(name="Status", key='status'),
1363
+ Column(name='Product Name', key='product_name'),
1364
+ Column(name='Members', key='members', format=True),
1365
+ Column(name='Product Manager', key='assigned_actors'),
1366
+ ]),
1367
+ Format(
1368
+ types=["REPORT", "HTML"],
1369
+ attributes=COMMON_COLUMNS + [
1370
+ Column(name="Status", key='status'),
1371
+ Column(name='Product Name', key='product_name'),
1372
+ Column(name='Identifier', key='identifier'),
1373
+ Column(name='Maturity', key='maturity'),
1374
+ Column(name='Service Life', key='service_life'),
1375
+ Column(name='Next Version', key='next_version'),
1376
+ Column(name='Withdraw Date', key='withdraw_date'),
1377
+ Column(name='Members', key='members', format=True),
1378
+ Column(name='Uses Products', key='uses_digital_products'),
1379
+ Column(name='Used by Products', key='used_by_digital_products'),
1380
+ Column(name='Product Manager', key='assigned_actors'),
1381
+ Column(name='License', key='governed_by'),
1382
+ Column(name='Solution Blueprint', key='solution_designs'),
1383
+ Column(name="Mermaid", key="mermaid")
1384
+ ],
1385
+ )
1386
+ ],
1387
+ action=ActionParameter(
1388
+ function="CollectionManager.find_collections",
1389
+ required_params=["search_string"],
1390
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1391
+ spec_params={"_type": "DigitalProductProperties",
1392
+ "metadata_element_subtypes": ["DigitalProduct"],
1393
+ "metadata_element_type": "DigitalProduct",
1394
+ },
1395
+ ),
1396
+ get_additional_props=ActionParameter(
1397
+ function="CollectionManager._extract_digital_product_properties",
1398
+ required_params=[],
1399
+ spec_params={},
1400
+ )
1401
+ ),
1402
+ "Digital-Products-Slim": FormatSet(
1403
+ target_type="DigitalProduct",
1404
+ heading="Digital Product Information",
1405
+ description="Attributes useful to Digital Products.",
1406
+ aliases=[],
1407
+ annotations={},
1408
+ family="Product Manager",
1409
+ formats=[
1410
+ Format(
1411
+ types=["FORM", "TABLE", "LIST", "MD"],
1412
+ attributes=[
1413
+ Column(name="Display Name", key='display_name'),
1414
+ Column(name="Type Name", key='type_name'),
1415
+ Column(name="Content Status", key='content_status'),
1416
+ Column(name="Deployment Status", key='deployment_status'),
1417
+ Column(name='Product Name', key='product_name'),
1418
+ Column(name='Members', key='members', format=True),
1419
+ # Column(name='Product Manager', key='assigned_actors'),
1420
+ Column(name='Contacts', key='actor_list'),
1421
+ ]),
1422
+ Format(
1423
+ types=["REPORT", "HTML"],
1424
+ attributes=COMMON_COLUMNS + [
1425
+ Column(name="Status", key='status'),
1426
+ Column(name='Product Name', key='product_name'),
1427
+ Column(name='Identifier', key='identifier'),
1428
+ Column(name='Maturity', key='maturity'),
1429
+ Column(name='Service Life', key='service_life'),
1430
+ Column(name='Next Version', key='next_version'),
1431
+ Column(name='Withdraw Date', key='withdraw_date'),
1432
+ Column(name='Members', key='members', format=True),
1433
+ Column(name='Uses Products', key='uses_digital_products'),
1434
+ Column(name='Used by Products', key='used_by_digital_products'),
1435
+ Column(name='Product Manager', key='assigned_actors'),
1436
+ Column(name='License', key='governed_by'),
1437
+ Column(name='Solution Blueprint', key='solution_designs'),
1438
+ Column(name="Mermaid", key="mermaid")
1439
+ ],
1440
+ )
1441
+ ],
1442
+ action=ActionParameter(
1443
+ function="CollectionManager.find_collections",
1444
+ required_params=["search_string"],
1445
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1446
+ spec_params={"_type": "DigitalProductProperties",
1447
+ "metadata_element_subtypes": ["DigitalProduct"],
1448
+ "metadata_element_type": "DigitalProduct",
1449
+ },
1450
+ ),
1451
+ get_additional_props=ActionParameter(
1452
+ function="CollectionManager._extract_digital_product_properties",
1453
+ required_params=[],
1454
+ spec_params={},
1455
+ )
1456
+ ),
1457
+ "Agreements": FormatSet(
1458
+ target_type="Agreement",
1459
+ heading="General Agreement Information",
1460
+ description="Attributes generic to all Agreements.",
1461
+ aliases=["DataSharingAgreement", "Agreement", "Subscriptions"],
1462
+ annotations={"wikilinks": ["[[Agreements]]", "[[Egeria]]"]},
1463
+ family="Product Manager",
1464
+ formats=[
1465
+ Format(
1466
+ types=["REPORT", "DICT", "TABLE", "LIST", "FORM"],
1467
+ attributes=COMMON_COLUMNS + COMMON_HEADER_COLUMNS + [
1468
+ Column(name='Identifier', key='identifier'),
1469
+ Column(name='Support Level', key='support_level'),
1470
+ Column(name='service Levels', key='service_levels'),
1471
+ Column(name='Agreement Items', key='agreement_items', format=True),
1472
+ Column(name='Members', key='members', format=True),
1473
+ ]
1474
+ )
1475
+ ],
1476
+ action=ActionParameter(
1477
+ function="CollectionManager.find_collections",
1478
+ required_params=["search_string"],
1479
+ spec_params={"metadata_element_subtypes": ["Agreement"]},
1480
+ # spec_params={},
1481
+ ),
1482
+ get_additional_props=ActionParameter(
1483
+ function="CollectionManager._extract_agreement_properties",
1484
+ required_params=[],
1485
+ spec_params={},
1486
+ ),
1487
+ ),
1488
+
1489
+ "Data-Dictionaries": FormatSet(
1490
+ target_type="Data Dictionary",
1491
+ heading="Data Dictionary Information",
1492
+ description="Attributes about Data Dictionary.",
1493
+ aliases=["Data Dict", "Data Dictionary"],
1494
+ annotations={"wikilinks": ["[[Data Dictionary]]"]},
1495
+ family="Data Designer",
1496
+ formats=[COMMON_FORMATS_ALL], # Reusing common formats and columns
1497
+ action=ActionParameter(
1498
+ function="CollectionManager.find_collections",
1499
+ required_params=["search_string"],
1500
+ spec_params={"metadata_element_subtypes": ["DataDictionary"]},
1501
+ )
1502
+ ),
1503
+
1504
+ "Data-Specifications": FormatSet(
1505
+ target_type="Data Specification",
1506
+ heading="Data Specification Information",
1507
+ description="Attributes about Data Specification.",
1508
+ aliases=["Data Spec", "DataSpec", "DataSpecification"],
1509
+ annotations={"wikilinks": ["[[Data Specification]]"]},
1510
+ family="Data Designer",
1511
+ formats=[
1512
+ Format(types=["REPORT", "HTML"],
1513
+ attributes=COMMON_COLUMNS + [Column(name="Mermaid", key='mermaidGraph'), ]),
1514
+ Format(types=["MERMAID"], attributes=[
1515
+ Column(name="Display Name", key='display_name'),
1516
+ Column(name="Mermaid", key='mermaidGraph'),
1517
+ ]),
1518
+ Format(types=["ALL"], attributes=COMMON_COLUMNS)], # Reusing common formats and columns
1519
+ action=ActionParameter(
1520
+ function="CollectionManager.find_collections",
1521
+ required_params=["search_string"],
1522
+ spec_params={"metadata_element_subtypes": ["DdataSpec"]},
1523
+ )
1524
+ ),
1525
+
1526
+ "Data-Structures": FormatSet(
1527
+ target_type="Data Structure",
1528
+ heading="Data Structure Information",
1529
+ description="Attributes about Data Structures.",
1530
+ aliases=["Data Structure", "DataStructures", "Data Structures", "Data Struct", "DataStructure"],
1531
+ annotations={"wikilinks": ["[[Data Structure]]"]},
1532
+ family="Data Designer",
1533
+ formats=[Format(types=["FORM", "DICT", "LIST"], attributes=COMMON_COLUMNS +
1534
+ [
1535
+ Column(name="In Data Specifications",
1536
+ key='in_data_spec'),
1537
+ Column(name="In Data Dictionaries",
1538
+ key='in_data_dictionary'),
1539
+ Column(name="Member Data Fields",
1540
+ key='member_data_fields')]
1541
+ ), # Reusing common formats and columns
1542
+ Format(types=["REPORT"], attributes=COMMON_COLUMNS +
1543
+ [
1544
+ Column(name="In Data Specifications", key='in_data_spec'),
1545
+ Column(name="In Data Dictionaries", key='in_data_dictionary'),
1546
+ Column(name="Member Data Fields", key='member_data_fields'),
1547
+ Column(name="Mermaid", key='mermaidGraph')
1548
+ ]
1549
+ )],
1550
+ action=ActionParameter(
1551
+ function="DataDesigner.find_data_structures",
1552
+ required_params=["search_string"],
1553
+ spec_params={},
1554
+ )
1555
+ ),
1556
+
1557
+ "Data-Fields": FormatSet(
1558
+ target_type="Data Field",
1559
+ heading="Data Field Information",
1560
+ description="Attributes about Data Fields.",
1561
+ aliases=["Data Field", "Data Fields", "DataFields"],
1562
+ annotations={"wikilinks": ["[[Data Field]]"]},
1563
+ family="Data Designer",
1564
+ formats=[Format(types=["MD", "FORM", "DICT", "LIST"], attributes=COMMON_COLUMNS + [
1565
+ Column(name="In Data Dictionaries", key='in_data_dictionary'),
1566
+ Column(name="In Data Structure", key='in_data_structure')]),
1567
+ Format(types=["REPORT"], attributes=COMMON_COLUMNS +
1568
+ [
1569
+ Column(name="In Data Structure", key='in_data_structure'),
1570
+ Column(name="In Data Dictionaries", key='in_data_dictionary'),
1571
+ Column(name="Member Data Fields", key='member_data_fields'),
1572
+ Column(name="Mermaid", key='mermaidGraph')
1573
+ ]
1574
+ )],
1575
+
1576
+ action=ActionParameter(
1577
+ function="DataDesigner.find_data_fields",
1578
+ required_params=["search_string"],
1579
+ spec_params={},
1580
+ )
1581
+ ),
1582
+ "Data-Classes": FormatSet(
1583
+ target_type="Data Class",
1584
+ heading="Data Class Information",
1585
+ description="Attributes about Data Classes",
1586
+ aliases=["Data Field", "Data Fields", "DataFields"],
1587
+ annotations={"wikilinks": ["[[Data Field]]"]},
1588
+ family="Data Designer",
1589
+ formats=[Format(types=["MD", "FORM", "DICT", "LIST"], attributes=COMMON_COLUMNS + [
1590
+ Column(name="Data Type", key='data_type'),
1591
+ Column(name="Specification", key='specification'),
1592
+ Column(name="In Data Dictionaries", key='in_data_dictionary'),
1593
+ Column(name="In Data Structure", key='in_data_structure')]),
1594
+ Format(types=["REPORT"], attributes=COMMON_COLUMNS +
1595
+ [
1596
+ Column(name="Data Type", key='data_type'),
1597
+ Column(name="Specification", key='specification'),
1598
+ Column(name="In Data Dictionaries", key='in_data_dictionary'),
1599
+ Column(name="Containing Data Class",
1600
+ key='containing_data_class'),
1601
+ Column(name="Specializes", key='specializes_data_class'),
1602
+ Column(name="Mermaid", key='mermaidGraph')
1603
+ ]
1604
+ )],
1605
+
1606
+ action=ActionParameter(
1607
+ function="DataDesigner.find_data_classes",
1608
+ required_params=["search_string"],
1609
+ spec_params={},
1610
+ )
1611
+ ),
1612
+ 'External-References': FormatSet(target_type='External-Reference',
1613
+ heading='External-Reference Attributes',
1614
+ description='External References',
1615
+ family="External References",
1616
+ formats=[
1617
+ Format(types=['MD', 'FORM', 'DICT'],
1618
+ attributes=[Column(name='Display Name', key='display_name'),
1619
+ Column(name='Description', key='description'),
1620
+ Column(name='Category', key='category'),
1621
+ Column(name='Reference Title', key='reference_title'),
1622
+ Column(name='Reference Abstract', key='reference_abstract'),
1623
+ Column(name='Authors', key='authors'),
1624
+ Column(name='Organization', key='organization'),
1625
+ Column(name='URL', key='reference_url'),
1626
+ Column(name='Sources', key='reference_sources'),
1627
+ Column(name='License', key='license'),
1628
+ Column(name='Copyright', key='copyright'),
1629
+ Column(name='Number of Pages', key='number_of_pages'),
1630
+ Column(name='Page Range', key='page_range'),
1631
+ Column(name='Publication Series', key='publication_series'),
1632
+ Column(name='Publication Series Volume',
1633
+ key='pub_series_volume'),
1634
+ Column(name='Publisher', key='publisher'),
1635
+ Column(name='First Publication Date', key='first_pub_date'),
1636
+ Column(name='Publication Date', key='pub_date'),
1637
+ Column(name='Publication City', key='pub_city'),
1638
+ Column(name='Publication Year', key='pub_year'),
1639
+ Column(name='Publication Numbers', key='pub_numbers'),
1640
+ Column(name='Version Identifier', key='current_version'),
1641
+ Column(name='Classifications', key='classifications'),
1642
+ Column(name='Qualified Name', key='qualified_name'),
1643
+ Column(name='GUID', key='guid')]),
1644
+ Format(types=['TABLE', 'LIST'],
1645
+ attributes=[Column(name='Display Name', key='display_name'),
1646
+
1647
+ Column(name='Category', key='category'),
1648
+ Column(name='Reference Title', key='reference_title'),
1649
+
1650
+ Column(name='Sources', key='reference_sources'),
1651
+ Column(name='License', key='license'),
1652
+ Column(name='Qualified Name', key='qualified_name'),
1653
+ ]),
1654
+ Format(types=["REPORT"],
1655
+ attributes=[Column(name='Display Name', key='display_name'),
1656
+ Column(name='Description', key='description'),
1657
+ Column(name='Category', key='category'),
1658
+ Column(name='Reference Title', key='reference_title'),
1659
+ Column(name='Reference Abstract', key='reference_abstract'),
1660
+ Column(name='Organization', key='organization'),
1661
+ Column(name='URL', key='reference_url'),
1662
+ Column(name='Sources', key='reference_sources'),
1663
+ Column(name='License', key='license'),
1664
+ Column(name='Qualified Name', key='qualified_name'),
1665
+ Column(name='Mermaid', key='mermaidGraph'),
1666
+ ]),
1667
+
1668
+ Format(types=["MERMAID"],
1669
+ attributes=[Column(name='Mermaid', key='mermaidGraph')]),
1670
+ ],
1671
+ action=ActionParameter(function='ExternalReference.find_external_references',
1672
+ required_params=['search_string'],
1673
+ optional_params=['page_size', 'start_from',
1674
+ 'starts_with', 'ends_with',
1675
+ 'ignore_case'], spec_params={
1676
+ 'metadata_element_subtypes': ['ExternalReference']})
1677
+ ),
1678
+
1679
+ "Governance Basics": FormatSet(
1680
+ target_type="Governance Definition",
1681
+ heading="Basic Governance-Definitions Information",
1682
+ description="Core Attributes useful to Governance-Definitions.",
1683
+ aliases=["BasicGovernance"],
1684
+ annotations={"wikilinks": ["[[Governance]]"]},
1685
+ family="Governance Officer",
1686
+ formats=[Format(types=["ALL"], attributes=GOVERNANCE_DEFINITIONS_BASIC)],
1687
+ action=ActionParameter(
1688
+ function="GovernanceOfficer.find_governance_definitions",
1689
+ required_params=["search_string"],
1690
+ spec_params={},
1691
+ )
1692
+ ),
1693
+ "Governance Definitions": FormatSet(
1694
+ target_type="Governance Definition",
1695
+ heading="Governance-Definitions Information",
1696
+ description="Attributes useful to Governance-Definitions.",
1697
+ aliases=["GovernanceDefinitions"],
1698
+ annotations={"wikilinks": ["[[Governance]]"]},
1699
+ family="Governance Officer",
1700
+ question_spec=[{'perspectives': ["ANY"], 'questions': WHO + WHAT + WHEN}],
1701
+ formats=[Format(types=["ALL"], attributes=GOVERNANCE_DEFINITIONS_COLUMNS)],
1702
+ action=ActionParameter(
1703
+ function="GovernanceOfficer.find_governance_definitions",
1704
+ required_params=["search_string"],
1705
+ spec_params={},
1706
+ )
1707
+ ),
1708
+ "Governance Def": FormatSet(
1709
+ target_type="Governance Definition",
1710
+ heading="Governance-Definitions Information",
1711
+ description="Attributes useful to Governance-Definitions.",
1712
+ aliases=["GovernanceDefinitions"],
1713
+ annotations={"wikilinks": ["[[Governance]]"]},
1714
+ family="Governance Officer",
1715
+ formats=[Format(types=["ALL"], attributes=GOVERNANCE_DEFINITIONS_BASIC)],
1716
+ action=ActionParameter(
1717
+ function="GovernanceOfficer.find_governance_definitions",
1718
+ required_params=["search_string"],
1719
+ spec_params={
1720
+ "metadata_element_subtypes": ["GovernancePrinciple", "GovernanceStrategy", "GovernanceResponse"]},
1721
+ )
1722
+ ),
1723
+ 'Governance-Controls': FormatSet(target_type='Governance Control',
1724
+ heading='Control Attributes',
1725
+ description='Governance Control (Create).',
1726
+ family="Governance Officer",
1727
+ question_spec=[{'perspectives': ["Governance"], 'questions': WHO + WHAT + WHEN + [
1728
+ "What governance controls have been defined?",
1729
+ "What measurements and measurement targets have been defined for governance controls?",
1730
+ "What are the implications of the governance controls?",
1731
+ "What are the risks associated with the governance controls?",
1732
+ ]}],
1733
+ formats=[
1734
+ Format(types=['DICT', 'MD', 'FORM', 'REPORT'],
1735
+ attributes=[Column(name='Display Name', key='display_name'),
1736
+ Column(name='Summary', key='summary'),
1737
+ Column(name='Description', key='description'),
1738
+ Column(name='Category', key='category'),
1739
+ Column(name='Domain Identifier', key='domain_identifier'),
1740
+ Column(name='Identifier', key='identifier'),
1741
+ Column(name='Version Identifier', key='version_identifier'),
1742
+ Column(name='Usage', key='usage'),
1743
+ Column(name='Scope', key='scope'),
1744
+ Column(name='Importance', key='importance'),
1745
+ Column(name='measurement', key='measurement'),
1746
+ Column(name='target', key='target'),
1747
+ Column(name='Implications', key='implications'),
1748
+ Column(name='Outcomes', key='outcomes'),
1749
+ Column(name='Results', key='results'),
1750
+ Column(name='Status', key='element_status'),
1751
+ Column(name='User Defined Status',
1752
+ key='user_defined_status'),
1753
+ Column(name='Qualified Name', key='qualified_name'),
1754
+ Column(name='GUID', key='guid')
1755
+ ]),
1756
+ Format(types=['TABLE', 'LIST'],
1757
+ attributes=[Column(name='Display Name', key='display_name'),
1758
+ Column(name='Summary', key='summary'),
1759
+ Column(name='Category', key='category'),
1760
+ Column(name='Identifier', key='identifier'),
1761
+ Column(name='Usage', key='usage'),
1762
+ Column(name='Status', key='element_status'),
1763
+ Column(name='Qualified Name', key='qualified_name'),
1764
+ ])
1765
+ ],
1766
+ action=ActionParameter(
1767
+ function="GovernanceOfficer.find_governance_definitions",
1768
+ required_params=["search_string"],
1769
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1770
+ spec_params={"metadata_element_subtypes": ["GovernanceControl"]},
1771
+ )
1772
+ ),
1773
+ 'Governance-Process': FormatSet(target_type='Governance Process',
1774
+ heading='Governance Process Attributes',
1775
+ description='Governance Process Attributes.',
1776
+ family="Governance Officer",
1777
+ formats=[
1778
+ Format(types=['TABLE', 'LIST', 'MD', 'FORM', 'REPORT'],
1779
+ attributes=[Column(name='Display Name', key='display_name'),
1780
+ Column(name='Description', key='description'),
1781
+ Column(name='Category', key='category'),
1782
+ Column(name='Qualified Name', key='qualified_name'),
1783
+ Column(name='GUID', key='guid')
1784
+ ]),
1785
+ Format(types=['DICT'],
1786
+ attributes=[Column(name='Display Name', key='display_name'),
1787
+ Column(name='Summary', key='summary'),
1788
+ Column(name='Category', key='category'),
1789
+ Column(name='Status', key='element_status'),
1790
+ Column(name='Qualified Name', key='qualified_name'),
1791
+ ])
1792
+ ],
1793
+ action=ActionParameter(
1794
+ function="GovernanceOfficer.find_governance_definitions",
1795
+ required_params=["search_string"],
1796
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1797
+ spec_params={"metadata_element_subtypes": ["GovernanceActionProcess"]},
1798
+ )
1799
+ ),
1800
+ "Valid-Value-Def": FormatSet(
1801
+ target_type="Valid Value Definition",
1802
+ heading="Valid Value Definitions Information",
1803
+ description="Attributes useful to Valid Value Definitions.",
1804
+ aliases=[],
1805
+ annotations={"wikilinks": ["[[VV-Def]]"]},
1806
+ family="General",
1807
+ formats=[Format(types=["ALL"], attributes=COMMON_COLUMNS +
1808
+ [Column(name='Data Type', key='data_type'),
1809
+ Column(name='Preferred Value', key='preferred_value'),
1810
+ Column(name='Usage', key='usage'),
1811
+ Column(name='Scope', key='scope'),
1812
+ ])
1813
+ ],
1814
+ action=ActionParameter(
1815
+ function="reference_data.find_valid_value_definitions",
1816
+ required_params=["search_string"],
1817
+ spec_params={},
1818
+ )
1819
+ ),
1820
+
1821
+ 'License-Type': FormatSet(target_type='License Type',
1822
+ heading='License Type Attributes',
1823
+ description='Attributes of a License type.',
1824
+ family="Governance Officer",
1825
+ formats=[
1826
+ Format(types=['DICT', 'MD', 'FORM', 'REPORT'],
1827
+ attributes=[Column(name='Display Name', key='display_name'),
1828
+ Column(name='Summary', key='summary'),
1829
+ Column(name='Description', key='description'),
1830
+ Column(name='Category', key='category'),
1831
+ Column(name='Domain Identifier', key='domain_identifier'),
1832
+ Column(name='Identifier', key='identifier'),
1833
+ Column(name='Version Identifier', key='version_identifier'),
1834
+ Column(name='Usage', key='usage'),
1835
+ Column(name='Scope', key='scope'),
1836
+ Column(name='Importance', key='importance'),
1837
+ Column(name='measurement', key='measurement'),
1838
+ Column(name='target', key='target'),
1839
+ Column(name='Implications', key='implications'),
1840
+ Column(name='Outcomes', key='outcomes'),
1841
+ Column(name='Results', key='results'),
1842
+ Column(name='Status', key='element_status'),
1843
+ Column(name='User Defined Status', key='user_defined_status'),
1844
+ Column(name='Qualified Name', key='qualified_name'),
1845
+ Column(name='GUID', key='guid')
1846
+ ]),
1847
+ Format(types=['TABLE', 'LIST'],
1848
+ attributes=[Column(name='Display Name', key='display_name'),
1849
+ Column(name='Summary', key='summary'),
1850
+ Column(name='Category', key='category'),
1851
+ Column(name='Identifier', key='identifier'),
1852
+ Column(name='Usage', key='usage'),
1853
+ Column(name='Status', key='element_status'),
1854
+ Column(name='Qualified Name', key='qualified_name'),
1855
+ ])
1856
+ ],
1857
+ action=ActionParameter(
1858
+ function="GovernanceOfficer.find_governance_definitions",
1859
+ required_params=["search_string"],
1860
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1861
+ spec_params={"metadata_element_subtypes": ["LicenseType"]},
1862
+ )
1863
+ ),
1864
+
1865
+ "Governance Policies": FormatSet(
1866
+ target_type="GovernancePolicy",
1867
+ heading="Governance-Definitions Information",
1868
+ description="Attributes useful to Governance-Definitions.",
1869
+ aliases=["GovernanceDefinitions"],
1870
+ annotations={"wikilinks": ["[[Governance]]"]},
1871
+ family="Governance Officer",
1872
+ formats=[Format(types=["ALL"], attributes=GOVERNANCE_DEFINITIONS_COLUMNS)],
1873
+ action=ActionParameter(
1874
+ function="GovernanceOfficer.find_governance_definitions",
1875
+ required_params=["search_string"],
1876
+ optional_params=OPTIONAL_SEARCH_PARAMS,
1877
+ spec_params={"metadata_element_subtypes": ["GovernancePolicy"]},
1878
+ )
1879
+ )
1880
+
1881
+ }
1882
+ )
1883
+
1884
+ # Build initial combined specs, then reorganize by family and slugged names
1885
+ _initial_combined_specs = combine_format_set_dicts(base_report_specs, generated_format_sets)
1886
+
1887
+ # Utilities for reorganizing specs by family and normalizing labels
1888
+ import re as _re
1889
+
1890
+
1891
+ def _slugify_label(label: str) -> str:
1892
+ """Turn a display label into a key by collapsing whitespace to '-'.
1893
+ Keeps existing hyphens, trims outer whitespace, and collapses multiple dashes.
1894
+ """
1895
+ if not isinstance(label, str):
1896
+ return str(label)
1897
+ s = label.strip()
1898
+ s = _re.sub(r"\s+", "-", s)
1899
+ s = _re.sub(r"-+", "-", s)
1900
+ return s
1901
+
1902
+
1903
+ def _add_alias(fs: FormatSet, alias: str) -> None:
1904
+ try:
1905
+ if alias and alias not in fs.aliases:
1906
+ fs.aliases.append(alias)
1907
+ except Exception:
1908
+ # Ensure aliases exists even if not initialized
1909
+ try:
1910
+ fs.aliases = list(set((getattr(fs, 'aliases', []) or []) + [alias]))
1911
+ except Exception:
1912
+ pass
1913
+
1914
+
1915
+ def _build_family_registries(specs: FormatSetDict) -> dict[str, FormatSetDict]:
1916
+ """Group specs by family and return mapping family -> FormatSetDict with slugified keys.
1917
+ - Missing/blank family -> "General"
1918
+ - Keys are slugified (spaces -> '-')
1919
+ - If slug differs from original, add original as an alias for backward compatibility
1920
+ - Within each family, entries are alphabetized by slugified name (case-insensitive)
1921
+ - Disambiguate collisions by appending numeric suffixes
1922
+ """
1923
+ families: dict[str, FormatSetDict] = {}
1924
+ for orig_name, fs in specs.items():
1925
+ fam_raw = getattr(fs, 'family', None)
1926
+ family = (fam_raw or '').strip() or 'General'
1927
+ fam_dict = families.setdefault(family, FormatSetDict())
1928
+
1929
+ base_slug = _slugify_label(orig_name)
1930
+ slug = base_slug
1931
+ suffix = 2
1932
+ while slug in fam_dict:
1933
+ slug = f"{base_slug}-{suffix}"
1934
+ suffix += 1
1935
+ # Add alias if the key is changing
1936
+ if slug != orig_name:
1937
+ _add_alias(fs, orig_name)
1938
+ # Also add a space-restored alias if someone passes slug with spaces (reverse unlikely but cheap)
1939
+ maybe_space = orig_name.replace('-', ' ')
1940
+ if maybe_space != orig_name:
1941
+ _add_alias(fs, maybe_space)
1942
+ fam_dict[slug] = fs
1943
+
1944
+ # Sort each family by key and rebuild as FormatSetDict in that order (preserves insertion order)
1945
+ for fam, fdict in list(families.items()):
1946
+ ordered = FormatSetDict()
1947
+ for key in sorted(list(fdict.keys()), key=lambda s: s.lower()):
1948
+ ordered[key] = fdict[key]
1949
+ families[fam] = ordered
1950
+ return families
1951
+
1952
+
1953
+ # Build family registries and a merged overall report_specs ordered by family then name
1954
+ family_report_specs = _build_family_registries(_initial_combined_specs)
1955
+
1956
+ _report_specs_merged = FormatSetDict()
1957
+ for fam_name in sorted(family_report_specs.keys(), key=lambda s: s.lower()):
1958
+ fam_dict = family_report_specs[fam_name]
1959
+ for key, fs in fam_dict.items():
1960
+ _report_specs_merged[key] = fs
1961
+
1962
+ report_specs = _report_specs_merged
1963
+
1964
+
1965
+ def select_report_spec(kind: str, output_type: str) -> dict | None:
1966
+ """
1967
+ Retrieve the appropriate output set configuration dictionary based on `kind` and `output_type`.
1968
+
1969
+ Intent of special output_type values:
1970
+ - "ANY": Discovery-only. Resolve the FormatSet (including aliases), action, and metadata, but DO NOT
1971
+ resolve a concrete format. Callers typically use this to check existence or to later pick a specific type
1972
+ via get_report_spec_match(...).
1973
+
1974
+ :param kind: The kind of output set (e.g., "Referenceable", "Collections"). Aliases are supported.
1975
+ :param output_type: The desired output format type (e.g., "DICT", "LIST", "REPORT"), or "ANY".
1976
+ :return: The matched output set dictionary or None if no match is found.
1977
+ """
1978
+ # Normalize the output type to uppercase for consistency
1979
+ output_type = output_type.upper()
1980
+ output_struct: dict = {}
1981
+
1982
+ # Step 1: Check if `kind` exists in the `report_specs` dictionary
1983
+ element = report_specs.get(kind)
1984
+
1985
+ # Step 2: If not found, attempt to match `kind` in aliases
1986
+ if element is None:
1987
+ for key, value in report_specs.items():
1988
+ aliases = value.aliases
1989
+ if kind in aliases:
1990
+ element = value
1991
+ break
1992
+
1993
+ # Step 3: If still not found, return None
1994
+ if element is None:
1995
+ msg = f"No matching column set found for kind='{kind}' and output type_name = '{output_type}'."
1996
+ logger.error(msg)
1997
+ return None
1998
+ else:
1999
+ # Convert FormatSet to dictionary for backward compatibility
2000
+ output_struct["aliases"] = element.aliases
2001
+ output_struct["heading"] = element.heading
2002
+ output_struct["description"] = element.description
2003
+ output_struct["annotations"] = element.annotations
2004
+ # Include target_type for callers that need to know the intended target entity type
2005
+ output_struct["target_type"] = element.target_type
2006
+ if element.action:
2007
+ # Convert ActionParameter to dictionary for backward compatibility
2008
+ output_struct["action"] = element.action.model_dump()
2009
+ if element.get_additional_props:
2010
+ output_struct["get_additional_props"] = element.get_additional_props.dict()
2011
+
2012
+ # If this was just a validation that the format set could be found then the output type is ANY - so just return.
2013
+ if output_type == "ANY":
2014
+ return output_struct
2015
+
2016
+ # Step 4: Search for a matching format in the `formats` list
2017
+ for format in element.formats:
2018
+ if output_type in format.types:
2019
+ # Convert Format to dictionary for backward compatibility
2020
+ output_struct["formats"] = format.dict()
2021
+ return output_struct
2022
+
2023
+ # Step 5: Handle the fallback case of "ALL"
2024
+ for format in element.formats:
2025
+ if "ALL" in format.types:
2026
+ # Convert Format to dictionary for backward compatibility
2027
+ output_struct["formats"] = format.dict()
2028
+ return output_struct
2029
+
2030
+ # Step 6: If no match is found, return None
2031
+ logger.error(f"No matching format found for kind='{kind}' with output type_name = '{output_type}'.")
2032
+ return None
2033
+
2034
+
2035
+ def report_spec_list(*, show_family: bool = False, sort_by_family: bool = False, return_kind: str = "strings") \
2036
+ -> list[str] | str | list[dict]:
2037
+ """
2038
+ Return the available report specs in one of three forms: strings (default), a Markdown table, or records.
2039
+
2040
+ Parameters
2041
+ - show_family: when True and return_kind=="strings", include the family tag alongside each name (e.g., "Collections [Catalog]")
2042
+ - sort_by_family: when True, sort results by family (case-insensitive; empty/no-family first),
2043
+ then alphabetize by name within each family (case-insensitive). When False, preserve insertion order.
2044
+ - return_kind: one of {"strings", "markdown_table", "markdown", "records", "dicts"}
2045
+ - "strings" (default): returns list[str] (optionally decorated with family when show_family=True)
2046
+ - "markdown_table"/"markdown": returns a Markdown table string with columns: Family | Report Name | Description
2047
+ - "records"/"dicts": returns a list of dicts: {"family": str|None, "name": str, "description": str}
2048
+
2049
+ Returns
2050
+ - list[str] when return_kind=="strings"
2051
+ - str when return_kind in {"markdown_table", "markdown"}
2052
+ - list[dict] when return_kind in {"records", "dicts"}
2053
+
2054
+ Notes
2055
+ - Default behavior remains backward-compatible with previous implementation: calling with no
2056
+ arguments returns only names in insertion order.
2057
+ """
2058
+ # Build list of (name, FormatSet)
2059
+ items = list(report_specs.items())
2060
+
2061
+ if sort_by_family:
2062
+ def _key(n_fs: tuple[str, FormatSet]):
2063
+ name, fs = n_fs
2064
+ fam = (getattr(fs, "family", None) or "").strip().lower()
2065
+ return (fam, name.lower())
2066
+
2067
+ items.sort(key=_key)
2068
+
2069
+ rk = (return_kind or "strings").strip().lower()
2070
+
2071
+ if rk in ("markdown_table", "markdown",):
2072
+ # Build rows for the markdown table
2073
+ def _esc(text: str) -> str:
2074
+ # Replace pipes and newlines to keep table intact
2075
+ return str(text).replace("|", "\\|").replace("\n", " ")
2076
+
2077
+ header = "| Family | Report Name | Description |\n|---|---|---|"
2078
+ lines: list[str] = [header]
2079
+ for name, fs in items:
2080
+ fam = (getattr(fs, "family", None) or "").strip()
2081
+ desc = getattr(fs, "description", "") or ""
2082
+ lines.append(f"| {_esc(fam)} | {_esc(name)} | {_esc(desc)} |")
2083
+ return "\n".join(lines)
2084
+
2085
+ if rk in ("records", "dicts"):
2086
+ records: list[dict] = []
2087
+ for name, fs in items:
2088
+ records.append({
2089
+ "family": getattr(fs, "family", None),
2090
+ "name": name,
2091
+ "description": getattr(fs, "description", "") or "",
2092
+ })
2093
+ return records
2094
+
2095
+ # Default: strings
2096
+ if show_family:
2097
+ out: list[str] = []
2098
+ for name, fs in items:
2099
+ fam = getattr(fs, "family", None)
2100
+ if fam and str(fam).strip():
2101
+ out.append(f"{name} [{fam}]")
2102
+ else:
2103
+ out.append(name)
2104
+ return out
2105
+ else:
2106
+ # Names only
2107
+ return [name for name, _ in items]
2108
+
2109
+
2110
+ def list_mcp_format_sets() -> dict:
2111
+ """
2112
+ Returns only those format set names that can be safely exposed as MCP tools.
2113
+ A format set is eligible if it has a DICT format or an ALL catch-all format.
2114
+
2115
+ This allows MCP to prefer machine-consumable outputs and avoid side effects.
2116
+ """
2117
+
2118
+ return {
2119
+ name: {
2120
+ "description": fs.description,
2121
+ "target_type": fs.target_type,
2122
+ "required_params": ", ".join(fs.action.required_params) or "",
2123
+ "optional_params": ", ".join(fs.action.optional_params) or "",
2124
+ }
2125
+ for name, fs in sorted(report_specs.items())
2126
+ if fs and fs.action and any(
2127
+ format_type in ["DICT", "ALL"]
2128
+ for format_obj in fs.formats
2129
+ for format_type in format_obj.types
2130
+ )
2131
+ }
2132
+
2133
+
2134
+ def get_report_spec_heading(format_set: str) -> str:
2135
+ """
2136
+ Gets the heading of a format set.
2137
+
2138
+ Args:
2139
+ format_set: The name of the format set
2140
+
2141
+ Returns:
2142
+ str: The heading of the format set
2143
+ """
2144
+ return report_specs[format_set].heading
2145
+
2146
+
2147
+ def get_report_spec_description(format_set: str) -> str:
2148
+ """
2149
+ Gets the description of a format set.
2150
+
2151
+ Args:
2152
+ format_set: The name of the format set
2153
+
2154
+ Returns:
2155
+ str: The description of the format set
2156
+ """
2157
+ return report_specs[format_set].description
2158
+
2159
+
2160
+ def get_report_spec_match(format_set: Union[dict, FormatSet], output_format: str) -> dict:
2161
+ """
2162
+ Matches a format set with a specific output format.
2163
+
2164
+ Args:
2165
+ format_set: The format set to match, either a FormatSet instance or a dictionary
2166
+ output_format: The output format to match
2167
+
2168
+ Returns:
2169
+ dict: The format set with the matching format
2170
+ """
2171
+ # Convert FormatSet to dictionary if needed
2172
+ if isinstance(format_set, FormatSet):
2173
+ format_set_dict = format_set.dict()
2174
+ else:
2175
+ format_set_dict = format_set
2176
+
2177
+ # Handle the case where format_set is a list (legacy code)
2178
+ if isinstance(format_set_dict, list):
2179
+ for format in format_set_dict.get("formats", []):
2180
+ if output_format in format.get("types", []):
2181
+ format_set_dict["formats"] = format
2182
+ return format_set_dict
2183
+
2184
+ # Handle the fallback case of "ALL"
2185
+ for format in format_set_dict.get("formats", []):
2186
+ if "ALL" in format.get("types", []):
2187
+ format_set_dict["formats"] = format
2188
+ return format_set_dict
2189
+ else:
2190
+ # Handle the case where format_set is a dictionary
2191
+ if "formats" in format_set_dict:
2192
+ formats = format_set_dict["formats"]
2193
+ if isinstance(formats, list):
2194
+ for format in formats:
2195
+ if output_format in format.get("types", []):
2196
+ format_set_dict["formats"] = format
2197
+ return format_set_dict
2198
+
2199
+ # Handle the fallback case of "ALL"
2200
+ for format in formats:
2201
+ if "ALL" in format.get("types", []):
2202
+ format_set_dict["formats"] = format
2203
+ return format_set_dict
2204
+ else:
2205
+ # Handle the case where format_set is a dictionary from select_report_spec with the "ANY" output type
2206
+ # In this case, we need to look up the format set by name and get the formats
2207
+ if "heading" in format_set_dict and "description" in format_set_dict:
2208
+ # Try to find the format set by heading
2209
+ for key, value in report_specs.items():
2210
+ if value.heading == format_set_dict["heading"] and value.description == format_set_dict[
2211
+ "description"]:
2212
+ # Found the format set, now find the matching format
2213
+ for format in value.formats:
2214
+ if output_format in format.types:
2215
+ format_set_dict["formats"] = format.dict()
2216
+ # Ensure target_type is included when reconstructing dict
2217
+ format_set_dict["target_type"] = value.target_type
2218
+ return format_set_dict
2219
+
2220
+ # Handle the fallback case of "ALL"
2221
+ for format in value.formats:
2222
+ if "ALL" in format.types:
2223
+ format_set_dict["formats"] = format.dict()
2224
+ # Ensure target_type is included when reconstructing dict
2225
+ format_set_dict["target_type"] = value.target_type
2226
+ return format_set_dict
2227
+
2228
+ # If no match is found, return the original format set
2229
+ return format_set_dict
2230
+
2231
+
2232
+ def save_report_specs(file_path: str, format_set_names: List[str] = None) -> None:
2233
+ """
2234
+ Save output format sets to a JSON file.
2235
+
2236
+ This function allows saving all format sets or a subset of format sets to a JSON file.
2237
+ The saved format sets can later be loaded using the `load_report_specs` function.
2238
+
2239
+ Args:
2240
+ file_path: The path to save the file to
2241
+ format_set_names: Optional list of format set names to save. If None, all format sets are saved.
2242
+ """
2243
+ if format_set_names is None:
2244
+ # Save all format sets
2245
+ report_specs.save_to_json(file_path)
2246
+ logger.info(f"All format sets saved to {file_path}")
2247
+ else:
2248
+ # Save only specified format sets
2249
+ subset = FormatSetDict()
2250
+ for name in format_set_names:
2251
+ format_set = report_specs.get(name)
2252
+ if format_set:
2253
+ subset[name] = format_set
2254
+ else:
2255
+ logger.warning(f"Format set '{name}' not found, skipping")
2256
+
2257
+ if subset:
2258
+ subset.save_to_json(file_path)
2259
+ logger.info(f"Selected format sets saved to {file_path}")
2260
+ else:
2261
+ logger.warning(f"No valid format sets to save, file not created")
2262
+
2263
+
2264
+ def load_report_specs(file_path: str, merge: bool = True) -> None:
2265
+ """
2266
+ Load output format sets from a JSON file.
2267
+
2268
+ This function loads format sets from a JSON file and either merges them with the existing
2269
+ format sets or replaces the existing format sets.
2270
+
2271
+ Args:
2272
+ file_path: The path to load the file from
2273
+ merge: If True, merge with existing format sets. If False, replace existing format sets.
2274
+ """
2275
+ global report_specs
2276
+ try:
2277
+ loaded_sets = FormatSetDict.load_from_json(file_path)
2278
+
2279
+ if merge:
2280
+ # Merge with existing format sets
2281
+ for key, value in loaded_sets.items():
2282
+ report_specs[key] = value
2283
+ logger.info(f"Format sets from {file_path} merged with existing format sets")
2284
+ else:
2285
+ # Replace existing format sets
2286
+ report_specs = loaded_sets
2287
+ logger.info(f"Existing format sets replaced with format sets from {file_path}")
2288
+ except Exception as e:
2289
+ logger.error(f"Error loading format sets from {file_path}: {e}")
2290
+ raise
2291
+
2292
+
2293
+ def load_user_report_specs() -> None:
2294
+ """
2295
+ Load all user-defined format sets from the user format sets directory.
2296
+
2297
+ This function loads all JSON files in the user format sets directory and merges
2298
+ the format sets with the existing format sets.
2299
+ """
2300
+ if not os.path.exists(USER_FORMAT_SETS_DIR):
2301
+ logger.debug(f"User format sets directory {USER_FORMAT_SETS_DIR} does not exist")
2302
+ return
2303
+
2304
+ # Load all JSON files in the directory
2305
+ for file_path in Path(USER_FORMAT_SETS_DIR).glob("*.json"):
2306
+ try:
2307
+ load_report_specs(str(file_path), merge=True)
2308
+ except Exception as e:
2309
+ logger.error(f"Error loading format sets from {file_path}: {e}")
2310
+
2311
+
2312
+ def report_spec_markdown() -> str:
2313
+ """Return a markdown list of all output format sets with target type, aliases, and column names.
2314
+
2315
+ This function is intended for external use to document available format sets.
2316
+ It generates a markdown string containing sections for each format set. For each
2317
+ set, it lists:
2318
+ - Target type
2319
+ - Aliases (if any)
2320
+ - Available formats (types) and their column display names with keys
2321
+ """
2322
+ lines: list[str] = ["# Available Output Format Sets", ""]
2323
+ for name in sorted(report_specs.keys()):
2324
+ fs = report_specs.get(name)
2325
+ if not fs:
2326
+ continue
2327
+ lines.append(f"## {name}")
2328
+ if fs.heading:
2329
+ lines.append(f"- Heading: {fs.heading}")
2330
+ if fs.description:
2331
+ lines.append(f"- Description: {fs.description}")
2332
+ lines.append(f"- Target type: {fs.target_type if hasattr(fs, 'target_type') else ''}")
2333
+ aliases = getattr(fs, 'aliases', []) or []
2334
+ if aliases:
2335
+ lines.append(f"- Aliases: {', '.join(aliases)}")
2336
+ # Formats
2337
+ try:
2338
+ fmt_list = fs.formats if hasattr(fs, 'formats') else []
2339
+ if fmt_list:
2340
+ lines.append("- Formats:")
2341
+ for fmt in fmt_list:
2342
+ types = ", ".join(fmt.types) if getattr(fmt, 'types', None) else ""
2343
+ lines.append(f" - Types: {types}")
2344
+ cols = getattr(fmt, 'columns', []) or []
2345
+ if cols:
2346
+ lines.append(" - Columns:")
2347
+ for col in cols:
2348
+ name_disp = getattr(col, 'name', '')
2349
+ key = getattr(col, 'key', '')
2350
+ lines.append(f" - {name_disp} ({key})")
2351
+ except Exception as e:
2352
+ logger.debug(f"Error while documenting format set {name}: {e}")
2353
+ lines.append("")
2354
+ return "\n".join(lines) + "\n"
2355
+
2356
+
2357
+ # Load user-defined format sets at module initialization
2358
+ try:
2359
+ load_user_report_specs()
2360
+ except Exception as e:
2361
+ logger.error(f"Error loading user-defined format sets: {e}")
2362
+ for key, format_set in report_specs.items():
2363
+ if not format_set.formats:
2364
+ logger.warning(f"FormatSet {key} has no formats defined.")
2365
+
2366
+ # =============================
2367
+ # Report format dynamic registry and new API (backward-compatible)
2368
+ # =============================
2369
+
2370
+ from typing import Optional
2371
+
2372
+ # Runtime and config-loaded registries (do not mutate built-ins)
2373
+ _RUNTIME_REPORT_FORMATS = FormatSetDict()
2374
+ _CONFIG_REPORT_FORMATS = FormatSetDict()
2375
+
2376
+
2377
+ class ReportFormatCollision(ValueError):
2378
+ pass
2379
+
2380
+
2381
+ def _add_with_collision_check(target: FormatSetDict, new: FormatSetDict, source: str) -> None:
2382
+ for label in new.keys():
2383
+ if label in target.keys():
2384
+ raise ReportFormatCollision(
2385
+ f"Report format label '{label}' already defined; conflict from {source}")
2386
+ # Now safe to merge
2387
+ for k, v in new.items():
2388
+ target[k] = v
2389
+
2390
+
2391
+ def _load_json_file(path: str) -> FormatSetDict:
2392
+ p = Path(os.path.expanduser(path)).resolve()
2393
+ if not p.exists():
2394
+ raise FileNotFoundError(f"Report formats JSON not found: {p}")
2395
+ return FormatSetDict.load_from_json(str(p))
2396
+
2397
+
2398
+ def refresh_report_specs() -> None:
2399
+ """Reload formats from configured JSON files and optional modules.
2400
+ Environment variables:
2401
+ - PYEGERIA_REPORT_FORMATS_JSON: comma-separated JSON file paths
2402
+ - PYEGERIA_REPORT_FORMATS_MODULES: optional comma-separated module callables (pkg.mod:func or pkg.mod.func)
2403
+ Collisions across sources will raise ReportFormatCollision.
2404
+ """
2405
+ global _CONFIG_REPORT_FORMATS
2406
+ _CONFIG_REPORT_FORMATS = FormatSetDict()
2407
+
2408
+ json_paths = os.getenv("PYEGERIA_REPORT_FORMATS_JSON", "").strip()
2409
+ if json_paths:
2410
+ for raw in json_paths.split(","):
2411
+ raw = raw.strip()
2412
+ if not raw:
2413
+ continue
2414
+ loaded = _load_json_file(raw)
2415
+ _add_with_collision_check(_CONFIG_REPORT_FORMATS, loaded, source=f"JSON:{raw}")
2416
+
2417
+ modules = os.getenv("PYEGERIA_REPORT_FORMATS_MODULES", "").strip()
2418
+ if modules:
2419
+ for m in modules.split(","):
2420
+ m = m.strip()
2421
+ if not m:
2422
+ continue
2423
+ # support both "pkg.mod.func" and "pkg.mod:func"
2424
+ if ":" in m:
2425
+ pkg, func = m.split(":", 1)
2426
+ else:
2427
+ pkg, func = m.rsplit(".", 1)
2428
+ mod = __import__(pkg, fromlist=[func])
2429
+ loader = getattr(mod, func)
2430
+ loaded = loader()
2431
+ if not isinstance(loaded, FormatSetDict):
2432
+ loaded = FormatSetDict(loaded)
2433
+ _add_with_collision_check(_CONFIG_REPORT_FORMATS, loaded, source=f"MODULE:{m}")
2434
+
2435
+
2436
+ def get_report_registry() -> FormatSetDict:
2437
+ """Combine built-ins, generated, config-loaded, and runtime formats.
2438
+ Enforce no duplicate labels across all sources.
2439
+ """
2440
+ combined = FormatSetDict()
2441
+ _add_with_collision_check(combined, base_report_specs, source="BUILTINS")
2442
+ _add_with_collision_check(combined, generated_format_sets, source="GENERATED")
2443
+ _add_with_collision_check(combined, _CONFIG_REPORT_FORMATS, source="CONFIG")
2444
+ _add_with_collision_check(combined, _RUNTIME_REPORT_FORMATS, source="RUNTIME")
2445
+ return combined
2446
+
2447
+
2448
+ def find_report_specs_by_perspective(perspective: str, *, case_insensitive: bool = True) -> list[dict]:
2449
+ """
2450
+ Return a list of dicts for report specs whose `question_spec` includes the given perspective.
2451
+
2452
+ Each dict has the shape:
2453
+ { 'perspective': <perspective>, 'report_spec': <label>, 'questions': [..questions..] }
2454
+
2455
+ Args:
2456
+ perspective: The perspective to search for (e.g., "Data Steward").
2457
+ case_insensitive: If True, compare perspectives case-insensitively.
2458
+
2459
+ Returns:
2460
+ List of dictionaries, one per matching question_spec item, sorted by 'report_spec'.
2461
+ """
2462
+ if not perspective:
2463
+ return []
2464
+ needle = perspective.strip()
2465
+ norm = (lambda s: (s or "").strip().lower()) if case_insensitive else (lambda s: (s or "").strip())
2466
+ needle_cmp = norm(needle)
2467
+
2468
+ results: list[dict] = []
2469
+ for label, fs in get_report_registry().items():
2470
+ qspec = getattr(fs, "question_spec", None)
2471
+ if not qspec:
2472
+ continue
2473
+ for item in qspec:
2474
+ perspectives = getattr(item, "perspectives", []) or []
2475
+ if any(norm(p) == needle_cmp for p in perspectives):
2476
+ questions = getattr(item, "questions", []) or []
2477
+ results.append({
2478
+ "perspective": perspective,
2479
+ "report_spec": label,
2480
+ "questions": questions,
2481
+ })
2482
+ return sorted(results, key=lambda d: d.get("report_spec", ""))
2483
+
2484
+
2485
+ def find_report_specs_by_question(
2486
+ question: str,
2487
+ *,
2488
+ case_insensitive: bool = True,
2489
+ substring: bool = True,
2490
+ ) -> list[dict]:
2491
+ """
2492
+ Return a list of dicts for report specs whose `question_spec` includes a matching example question.
2493
+
2494
+ Each dict has the shape:
2495
+ { 'question': <input question>, 'report_spec': <label>, 'perspectives': [..perspectives..] }
2496
+
2497
+ Args:
2498
+ question: The question to search for.
2499
+ case_insensitive: If True, compare questions case-insensitively.
2500
+ substring: If True, treat `question` as a substring to match within example questions;
2501
+ otherwise require exact match.
2502
+
2503
+ Returns:
2504
+ List of dictionaries, one per matching question_spec item, sorted by 'report_spec'.
2505
+ """
2506
+ if not question:
2507
+ return []
2508
+ needle = question.strip()
2509
+ norm = (lambda s: (s or "").strip().lower()) if case_insensitive else (lambda s: (s or "").strip())
2510
+ needle_cmp = norm(needle)
2511
+
2512
+ results: list[dict] = []
2513
+ for label, fs in get_report_registry().items():
2514
+ qspec = getattr(fs, "question_spec", None)
2515
+ if not qspec:
2516
+ continue
2517
+ for item in qspec:
2518
+ questions = getattr(item, "questions", []) or []
2519
+ hit = False
2520
+ for q in questions:
2521
+ qn = norm(q)
2522
+ if substring:
2523
+ if needle_cmp in qn:
2524
+ hit = True
2525
+ break
2526
+ else:
2527
+ if needle_cmp == qn:
2528
+ hit = True
2529
+ break
2530
+ if hit:
2531
+ perspectives = getattr(item, "perspectives", []) or []
2532
+ results.append({
2533
+ "question": question,
2534
+ "report_spec": label,
2535
+ "perspectives": perspectives,
2536
+ })
2537
+ return sorted(results, key=lambda d: d.get("report_spec", ""))
2538
+
2539
+
2540
+ def find_report_specs(
2541
+ *,
2542
+ perspective: str | None = None,
2543
+ question: str | None = None,
2544
+ report_spec: str | None = None,
2545
+ case_insensitive: bool = True,
2546
+ substring: bool = True,
2547
+ ) -> list[dict]:
2548
+ """
2549
+ Flexible finder that accepts optional filters and returns matching report_spec dicts.
2550
+
2551
+ Logical semantics: provided filters are ANDed; any filter not provided is treated as ANY.
2552
+
2553
+ Returned dict shape (one per matching question_spec item):
2554
+ { 'report_spec': <label>, 'perspectives': [...], 'questions': [...] }
2555
+
2556
+ The result list is sorted by 'report_spec'.
2557
+ """
2558
+ norm = (lambda s: (s or "").strip().lower()) if case_insensitive else (lambda s: (s or "").strip())
2559
+ persp_cmp = norm(perspective) if perspective else None
2560
+ quest_cmp = norm(question) if question else None
2561
+ rs_cmp = norm(report_spec) if report_spec else None
2562
+
2563
+ results: list[dict] = []
2564
+ for label, fs in get_report_registry().items():
2565
+ # filter on report_spec by label or alias
2566
+ if rs_cmp is not None:
2567
+ label_match = norm(label) == rs_cmp
2568
+ alias_match = any(norm(a) == rs_cmp for a in getattr(fs, "aliases", []) or [])
2569
+ if not (label_match or alias_match):
2570
+ continue
2571
+
2572
+ qspec = getattr(fs, "question_spec", None)
2573
+ if not qspec:
2574
+ # If there are no question specs, it cannot match perspective/question filters
2575
+ if persp_cmp is None and quest_cmp is None:
2576
+ # Only report_spec filter was provided and matched; emit a single entry with empty lists
2577
+ results.append({
2578
+ "report_spec": label,
2579
+ "perspectives": [],
2580
+ "questions": [],
2581
+ })
2582
+ continue
2583
+
2584
+ for item in qspec:
2585
+ perspectives = getattr(item, "perspectives", []) or []
2586
+ questions = getattr(item, "questions", []) or []
2587
+
2588
+ if persp_cmp is not None:
2589
+ if not any(norm(p) == persp_cmp for p in perspectives):
2590
+ continue
2591
+
2592
+ if quest_cmp is not None:
2593
+ q_hit = False
2594
+ for q in questions:
2595
+ qn = norm(q)
2596
+ if substring:
2597
+ if quest_cmp in qn:
2598
+ q_hit = True
2599
+ break
2600
+ else:
2601
+ if quest_cmp == qn:
2602
+ q_hit = True
2603
+ break
2604
+ if not q_hit:
2605
+ continue
2606
+
2607
+ results.append({
2608
+ "report_spec": label,
2609
+ "perspectives": perspectives,
2610
+ "questions": questions,
2611
+ })
2612
+
2613
+ return sorted(results, key=lambda d: d.get("report_spec", ""))
2614
+
2615
+
2616
+ def register_report_specs(new_formats: Union[FormatSetDict, dict], *, source: str = "runtime") -> None:
2617
+ """Dynamically add report formats at runtime. Raises on duplicate label."""
2618
+ global _RUNTIME_REPORT_FORMATS
2619
+ if not isinstance(new_formats, FormatSetDict):
2620
+ new_formats = FormatSetDict(new_formats)
2621
+ existing = get_report_registry()
2622
+ for label in new_formats.keys():
2623
+ if label in existing.keys():
2624
+ raise ReportFormatCollision(
2625
+ f"Report format label '{label}' already exists; cannot register from {source}")
2626
+ for k, v in new_formats.items():
2627
+ _RUNTIME_REPORT_FORMATS[k] = v
2628
+
2629
+
2630
+ def unregister_report_spec(label: str) -> bool:
2631
+ return bool(_RUNTIME_REPORT_FORMATS.pop(label, None))
2632
+
2633
+
2634
+ def clear_runtime_report_specs() -> None:
2635
+ _RUNTIME_REPORT_FORMATS.clear()
2636
+
2637
+
2638
+ def list_report_specs() -> list[str]:
2639
+ return list(get_report_registry().keys())
2640
+
2641
+
2642
+ def _select_from_registry(registry: FormatSetDict, kind: str, output_type: str) -> dict | None:
2643
+ # Normalize
2644
+
2645
+ output_type = output_type.upper()
2646
+ element: Optional[FormatSet] = registry.get(kind)
2647
+ if element is None:
2648
+ # try aliases
2649
+ for value in registry.values():
2650
+ if kind in value.aliases:
2651
+ element = value
2652
+ break
2653
+ if element is None:
2654
+ logger.error(f"No matching report format found for kind='{kind}' and output type_name = '{output_type}'.")
2655
+ return None
2656
+
2657
+ output_struct: dict = {
2658
+ "aliases": element.aliases,
2659
+ "heading": element.heading,
2660
+ "description": element.description,
2661
+ "question_spec": element.question_spec,
2662
+ "annotations": element.annotations,
2663
+ "target_type": element.target_type,
2664
+ }
2665
+ if element.action:
2666
+ output_struct["action"] = element.action.dict()
2667
+ if element.get_additional_props:
2668
+ output_struct["get_additional_props"] = element.get_additional_props.dict()
2669
+
2670
+ if output_type == "ANY":
2671
+ return output_struct
2672
+
2673
+ for fmt in element.formats:
2674
+ if output_type in fmt.types:
2675
+ output_struct["formats"] = fmt.dict()
2676
+ return output_struct
2677
+ for fmt in element.formats:
2678
+ if "ALL" in fmt.types:
2679
+ output_struct["formats"] = fmt.dict()
2680
+ return output_struct
2681
+ logger.error(f"No matching format found for kind='{kind}' with output type_name = '{output_type}'.")
2682
+ return None
2683
+
2684
+
2685
+ # New public API (preferred)
2686
+
2687
+ def select_report_format(kind: str, output_type: str) -> dict | None:
2688
+ return _select_from_registry(get_report_registry(), kind, output_type)
2689
+
2690
+
2691
+ def report_format_list() -> list[str]:
2692
+ return list_report_specs()
2693
+
2694
+
2695
+ def get_report_format_heading(fmt_name: str) -> Optional[str]:
2696
+ reg = get_report_registry()
2697
+ fs = reg.get(fmt_name)
2698
+ if fs is None:
2699
+ for k, v in reg.items():
2700
+ if fmt_name in v.aliases:
2701
+ return v.heading
2702
+ return None
2703
+ return fs.heading
2704
+
2705
+
2706
+ def get_report_format_description(fmt_name: str) -> Optional[str]:
2707
+ reg = get_report_registry()
2708
+ fs = reg.get(fmt_name)
2709
+ if fs is None:
2710
+ for k, v in reg.items():
2711
+ if fmt_name in v.aliases:
2712
+ return v.description
2713
+ return None
2714
+ return fs.description
2715
+
2716
+
2717
+ # Legacy names remain available (no change to behavior) and can be deprecated later.
2718
+ # Temporary aliases for backwards compatibility during migration
2719
+ select_report_spec = select_report_format