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
@@ -3,16 +3,16 @@ This file contains general utility functions for processing Egeria Markdown
3
3
  """
4
4
  import os
5
5
  import re
6
- import sys
7
- import json
8
6
  from datetime import datetime
9
7
  from typing import Any
10
8
  from loguru import logger
11
9
  from rich import print
12
10
  from rich.console import Console
13
11
  from rich.markdown import Markdown
14
- from pyegeria.utils import (camel_to_title_case, body_slimmer)
15
- from pyegeria._globals import DEBUG_LEVEL
12
+
13
+ from pyegeria import ServerClient, PyegeriaException
14
+ from pyegeria.core.utils import (camel_to_title_case)
15
+ from pyegeria.core._globals import DEBUG_LEVEL
16
16
  from md_processing.md_processing_utils.message_constants import message_types
17
17
 
18
18
  # Constants
@@ -34,10 +34,7 @@ EGERIA_GLOSSARY_PATH = os.environ.get("EGERIA_GLOSSARY_PATH", None)
34
34
  EGERIA_ROOT_PATH = os.environ.get("EGERIA_ROOT_PATH", "../../")
35
35
  EGERIA_INBOX_PATH = os.environ.get("EGERIA_INBOX_PATH", "md_processing/dr_egeria_inbox")
36
36
  EGERIA_OUTBOX_PATH = os.environ.get("EGERIA_OUTBOX_PATH", "md_processing/dr_egeria_outbox")
37
- LOG_FORMAT = "D <green> {time} </green> | {level} | {function} | {line} | {message} | {extra}"
38
- CONSOLE_LOG_FORMAT = "<green>{time}</green> | {message}"
39
37
 
40
- console = Console(width=EGERIA_WIDTH)
41
38
  GENERAL_GOVERNANCE_DEFINITIONS = ["Governance Definition", "Business Imperative", "Regulation Article", "Threat",
42
39
  "Governance Policy", "Governance Principle", "Governance Obligation",
43
40
  "Governance Approach",
@@ -54,20 +51,10 @@ GOVERNANCE_CONTROLS = ["Governance Control", "Governance Rule", "Service Level O
54
51
  ALL_GOVERNANCE_DEFINITIONS = GENERAL_GOVERNANCE_DEFINITIONS + GOVERNANCE_CONTROLS + ["Governance Strategy", "Regulation",
55
52
  "Security Group", "GovernanceMetric",
56
53
  "Naming Standard Rule", "TermsAndConditions", "Certification Type", "License Type"]
57
-
54
+ console = Console(width=EGERIA_WIDTH)
58
55
  debug_level = DEBUG_LEVEL
59
56
  global COMMAND_DEFINITIONS
60
57
 
61
- def setup_log():
62
- logger.remove()
63
- logger.add(sys.stderr, level="SUCCESS", format=CONSOLE_LOG_FORMAT, colorize=True)
64
- full_file_path = os.path.join(EGERIA_ROOT_PATH, EGERIA_INBOX_PATH, "data_designer_debug.log")
65
- # logger.add(full_file_path, rotation="1 day", retention="1 week", compression="zip", level="TRACE", format=log_format,
66
- # colorize=True)
67
- logger.add("debug_log", rotation="1 day", retention="1 week", compression="zip", level="INFO", format=LOG_FORMAT,
68
- colorize=True)
69
-
70
-
71
58
  def split_tb_string(input: str)-> [Any]:
72
59
  """Split the string and trim the items"""
73
60
  l = [item.strip() for item in re.split(r'[;,\n]+',input)] if input is not None else None
@@ -229,23 +216,17 @@ def find_key_with_value(value: str) -> str | None:
229
216
 
230
217
  def set_find_body(object_type: str, attributes: dict)->dict:
231
218
  prop_name = object_type.replace(" ", "")
232
-
233
- start = attributes.get('Start From', {}).get('value', 0)
234
- start_from = int(start) if start else 0
235
- page = attributes.get('Page Size', {}).get('value', 0)
236
- page_size = int(page) if page else 0
237
- depth = attributes.get('Graph Query Depth', {}).get('value', 0)
238
- depth = int(depth) if depth else 0
239
-
219
+ s = attributes.get('Search String', {}).get('value', None)
220
+ search_string = None if s =='*' else s
240
221
 
241
222
 
242
223
  body = {
243
224
  "class": "SearchStringRequestBody",
244
- "searchString": attributes.get('Search String', {}).get('value', None),
225
+ "searchString": search_string,
245
226
  "startsWith": attributes.get('Start With', {}).get('value', True),
246
227
  "endWith": attributes.get('End With', {}).get('value', False),
247
228
  "ignoreCase": attributes.get('Ignore Case', {}).get('value', False),
248
- "limitResultsByStatus": attributes.get('Limit Results By Status', {}).get('value', False),
229
+ "limitResultsByStatus": attributes.get('Limit Results By Status', {}).get('value', []),
249
230
  "startFrom": int(attributes.get('Start From', {}).get('value', 0)),
250
231
  "pageSize": int(attributes.get('Page Size', {}).get('value', 0)),
251
232
  # "metadataElementSubtypeNames": attributes.get('Metadata Element Subtype Name', {}).get('value', None),
@@ -253,13 +234,20 @@ def set_find_body(object_type: str, attributes: dict)->dict:
253
234
  "effectiveTime": attributes.get('Effective Time', {}).get('value', None),
254
235
  "governanceZoneFilter" : attributes.get('Governance Zone Filter', {}).get('value', None),
255
236
  "graphQueryDepth": int(attributes.get('Graph Query Depth', {}).get('value', 0)),
256
- "initialStatus": attributes.get('Status', {}).get('value', "ACTIVE"),
257
- "initialClassifications": {}}
237
+ }
258
238
 
259
239
  return body
260
240
 
261
241
 
262
242
  def set_create_body(object_type: str, attributes: dict)->dict:
243
+ """
244
+ Build the OUTER request body for a create action (NewElementRequestBody).
245
+
246
+ Notes on two-layer convention:
247
+ - Outer layer (this function): action wrapper with metadata like externalSource*, effectiveTime, anchor/parent hints, and an empty "properties" field.
248
+ - Inner layer: an element-type-specific Properties structure built by set_element_prop_body, set_product_body, set_data_field_body, etc.
249
+ Callers should build the inner body separately with the appropriate helper and then assign it to body["properties"].
250
+ """
263
251
  prop_name = object_type.replace(" ", "")
264
252
  body = {
265
253
  "class": "NewElementRequestBody",
@@ -275,6 +263,7 @@ def set_create_body(object_type: str, attributes: dict)->dict:
275
263
  "parentRelationshipTypeName": attributes.get('Parent Relationship Type Name', {}).get('value', None),
276
264
  "parentRelationshipProperties": attributes.get('Parent Relationship Properties', {}).get('value', None),
277
265
  "parentAtEnd1": attributes.get('Parent at End1', {}).get('value', True),
266
+ "anchorScopeGUID": attributes.get('Anchor Scope GUID', {}).get('guid', None),
278
267
  "properties": "",
279
268
  "initialStatus": attributes.get('Status', {}).get('value', "ACTIVE"),
280
269
  "initialClassifications": {}}
@@ -285,6 +274,13 @@ def set_create_body(object_type: str, attributes: dict)->dict:
285
274
 
286
275
 
287
276
  def set_update_body(object_type: str, attributes: dict)->dict:
277
+ """
278
+ Build the OUTER request body for an update action (UpdateElementRequestBody).
279
+
280
+ Two-layer convention:
281
+ - Outer layer (this function) provides action metadata and an empty "properties" slot.
282
+ - Inner layer must be constructed via element-specific helpers (e.g., set_element_prop_body) and assigned to the returned dict's "properties" key by the caller before invoking the client.
283
+ """
288
284
  return {
289
285
  "class" : "UpdateElementRequestBody",
290
286
  "externalSourceGUID": attributes.get('External Source GUID', {}).get('guid', None),
@@ -293,12 +289,34 @@ def set_update_body(object_type: str, attributes: dict)->dict:
293
289
  "effectiveTime": attributes.get('Effective Time', {}).get('value', None),
294
290
  "forLineage": attributes.get('For Lineage', {}).get('value', False),
295
291
  "forDuplicateProcessing": attributes.get('For Duplicate Processing', {}).get('value', False),
296
- "mergeUpdate": attributes.get('Merge Update', {}).get('value', True),
292
+ "mergeUpdate": attributes.get('Merge Update', {}).get('value', True),
297
293
  "properties": "",
298
294
  }
295
+ def set_rel_prop_body(object_type: str, attributes: dict)->dict:
296
+ prop_name = object_type.replace(" ", "")
297
+ display_name = attributes.get('Display Name', {}).get('value', None)
299
298
 
300
- def set_prop_body(object_type: str, qualified_name: str, attributes: dict)->dict:
299
+ return {
300
+ "class": prop_name + "Properties",
301
+ "description": attributes['Description'].get('value', None),
302
+ "label": attributes.get('Label', {}).get('value', None) or attributes.get('Link Label', {}).get('value', None),
303
+ "typeName" : attributes.get('Type Name', {}).get('value', None),
304
+ "effectiveFrom": attributes.get('Effective From', {}).get('value', None),
305
+ "effectiveTo": attributes.get('Effective To', {}).get('value', None),
306
+ "extendedProperties": attributes.get('Extended Properties', {}).get('value', None),
307
+ }
301
308
 
309
+ def set_element_prop_body(object_type: str, qualified_name: str, attributes: dict)->dict:
310
+ """
311
+ Build the INNER element-specific Properties body to be placed under the outer body's "properties" key.
312
+
313
+ This returns the typed properties structure (e.g., "ReferenceableProperties" subtypes) appropriate for the object_type.
314
+ Usage example:
315
+ - outer = set_create_body(object_type, attributes)
316
+ - props = set_element_prop_body(object_type, qualified_name, attributes)
317
+ - outer["properties"] = props
318
+ - client.create_xxx(outer)
319
+ """
302
320
  prop_name = object_type.replace(" ", "")
303
321
  display_name = attributes.get('Display Name', {}).get('value', None)
304
322
 
@@ -320,7 +338,7 @@ def set_prop_body(object_type: str, qualified_name: str, attributes: dict)->dict
320
338
  }
321
339
 
322
340
  def set_product_body(object_type: str, qualified_name: str, attributes: dict)->dict:
323
- prop_bod = set_prop_body(object_type, qualified_name, attributes)
341
+ prop_bod = set_element_prop_body(object_type, qualified_name, attributes)
324
342
  prop_bod["identifier"] = attributes.get('Identifier', {}).get('value', None)
325
343
  prop_bod["productName"] = attributes.get('Product Name', {}).get('value', None)
326
344
  prop_bod["maturity"] = attributes.get('Maturity', {}).get('value', None)
@@ -330,7 +348,21 @@ def set_product_body(object_type: str, qualified_name: str, attributes: dict)->d
330
348
  prop_bod["nextVersion"] = attributes.get('Next Version Date', {}).get('value', [])
331
349
  return prop_bod
332
350
 
333
-
351
+ def set_data_field_body(object_type: str, qualified_name: str, attributes: dict)->dict:
352
+ prop_bod = set_element_prop_body(object_type, qualified_name, attributes)
353
+ prop_bod["namespace"] = attributes.get('Namespace', {}).get('value', None)
354
+ prop_bod["aliases"] = attributes.get('Aliases', {}).get('value', [])
355
+ prop_bod["namePatterns"] = attributes.get('Name Patterns', {}).get('value', [])
356
+ prop_bod["defaultValue"] = attributes.get('Default Value', {}).get('value', None)
357
+ prop_bod["isNullable"] = attributes.get('Is Nullable', {}).get('value', None)
358
+ prop_bod["dataType"] = attributes.get('Data Type', {}).get('value', None)
359
+ prop_bod["units"] = attributes.get('Units', {}).get('value', None)
360
+ prop_bod["minimumLength"] = attributes.get('Minimum Length', {}).get('value', None)
361
+ prop_bod["length"] = attributes.get('Length', {}).get('value', None)
362
+ prop_bod["precision"] = attributes.get('Precision', {}).get('value', None)
363
+ prop_bod["orderedValues"] = attributes.get('Ordered Values', {}).get('value', [])
364
+ prop_bod["sortOrder"] = attributes.get('Sort Order', {}).get('value', None)
365
+ return prop_bod
334
366
 
335
367
  def set_update_status_body(object_type: str, attributes: dict)->dict:
336
368
  return {
@@ -343,7 +375,7 @@ def set_update_status_body(object_type: str, attributes: dict)->dict:
343
375
 
344
376
  def set_gov_prop_body(object_type: str, qualified_name: str, attributes: dict)->dict:
345
377
  prop_name = object_type.replace(" ", "")
346
- prop_bod = set_prop_body(object_type, qualified_name, attributes)
378
+ prop_bod = set_element_prop_body(object_type, qualified_name, attributes)
347
379
  prop_bod["domainIdentifier"] = attributes.get('Domain Identifier', {}).get('value', None)
348
380
  prop_bod["displayName"]= attributes.get('Display Name', {}).get('value', None)
349
381
  prop_bod['qualifiedName'] = qualified_name
@@ -355,7 +387,7 @@ def set_gov_prop_body(object_type: str, qualified_name: str, attributes: dict)->
355
387
  prop_bod["importance"] = attributes.get('Importance', {}).get('value', None)
356
388
  prop_bod["implications"] = attributes.get('Implication', {}).get('value', [])
357
389
  prop_bod["outcomes"] = attributes.get('Outcomes', {}).get('value', [])
358
- prop_bod["results"] = attributes.get('Results', {}).get('value', [])
390
+ prop_bod["results"] = attributes.get('Results', {}).get('value', []) or []
359
391
  prop_bod["effectiveFrom"] = attributes.get('Effective From', {}).get('value', None),
360
392
  prop_bod["effectiveTo"] = attributes.get('Effective To', {}).get('value', None),
361
393
  prop_bod["additionalProperties"] = attributes.get('Additional Properties', {}).get('value', None),
@@ -393,14 +425,22 @@ def update_gov_body_for_type(object_type: str, body: dict, attributes: dict) ->
393
425
  body['namePatterns'] = attributes.get('Name Patterns', {}).get('value', [])
394
426
  return body
395
427
  elif object_type in ["TermsAndConditions", "Certification Type", "License Type"]:
396
- body['entitlements'] = attributes.get('Entitlementss', {}).get('value', {})
397
- body['restrictions'] = attributes.get('Restrictions', {}).get('value', {})
398
- body['obligations'] = attributes.get('Obligations', {}).get('value', {})
428
+ entitlements = attributes.get('Entitlementss', {}).get('value', {}) if attributes.get('Entitlementss',None) else None
429
+ restrictions = attributes.get('Restrictions', {}).get('value', {}) if attributes.get('Restrictions',None) else None
430
+ obligations = attributes.get('Obligations', {}).get('value', {}) if attributes.get('Obligations',None) else None
431
+ body['entitlements'] = entitlements
432
+ body['restrictions'] = restrictions
433
+ body['obligations'] = obligations
399
434
 
400
435
  return body
401
436
 
402
437
 
403
438
  def set_rel_request_body(object_type: str, attributes: dict)->dict:
439
+ """
440
+ Build the OUTER request body for creating a relationship (NewRelationshipRequestBody).
441
+ The inner relationship properties must be assigned to the returned dict under the "properties" key,
442
+ commonly via set_rel_prop_body or set_rel_request_body_for_type.
443
+ """
404
444
  return {
405
445
  "class" : "NewRelationshipRequestBody",
406
446
  "externalSourceGUID": attributes.get('External Source GUID', {}).get('guid', None),
@@ -422,9 +462,27 @@ def set_peer_gov_def_request_body(object_type: str, attributes: dict)->dict:
422
462
  }
423
463
  return rel_body
424
464
 
465
+ def set_rel_request_body_for_type(object_type: str, attributes: dict)->dict:
466
+ """
467
+ Convenience helper that builds both layers (outer + inner) for a relationship of a known type.
468
+ It creates the outer NewRelationshipRequestBody via set_rel_request_body and fills rel_body["properties"]
469
+ with a typed properties structure under the "class" of f"{object_type}Properties".
470
+ """
471
+ rel_body = set_rel_request_body(object_type, attributes)
472
+ # class_prop = camel_to_title_case(object_type) + "Properties"
473
+ class_prop = f"{object_type}Properties"
474
+ rel_body["properties"] = {
475
+ "class" : class_prop,
476
+ "description": attributes.get('Description', {}).get('value', None),
477
+ "effectiveFrom": attributes.get('Effective From', {}).get('value', None),
478
+ "effectiveTo": attributes.get('Effective To', {}).get('value', None),
479
+ "label": attributes.get('Label', {}).get('value', None),
480
+ }
481
+ return rel_body
482
+
425
483
  def set_delete_request_body(object_type: str, attributes: dict)->dict:
426
484
  return {
427
- "class": "DeleteRequestBody",
485
+ "class": "DeleteElementRequestBody",
428
486
  "externalSourceGUID": attributes.get('External Source GUID', {}).get('guid', None),
429
487
  "externalSourceName": attributes.get('External Source Name', {}).get('value', None),
430
488
  "effectiveTime": attributes.get('Effective Time', {}).get('value', None),
@@ -463,10 +521,10 @@ def set_classifications(object_type: str, attributes: dict)->dict:
463
521
  classifications = attributes.get('Classifications', {}).get('name_list', None)
464
522
  body = None
465
523
  if classifications:
466
- body = {classification: {} for classification in classifications} if cclassifications else {}
524
+ body = {classification: {} for classification in classifications} if classifications else {}
467
525
  return body
468
526
 
469
- def set_collection_classifications(object_type: str, attributes: dict, obj_types: list[str])->dict:
527
+ def set_object_classifications(object_type: str, attributes: dict, obj_types: list[str])->dict:
470
528
  classifications = attributes.get('Classifications', {}).get('name_list', None)
471
529
  obj = object_type.replace(" ", "")
472
530
  if object_type in obj_types:
@@ -480,4 +538,41 @@ def set_collection_classifications(object_type: str, attributes: dict, obj_types
480
538
  if classifications:
481
539
  for classification in classifications:
482
540
  body[classification] = {"class" : f"{classification}Properties"}
483
- return body
541
+ return body
542
+
543
+ def add_search_keywords(client: ServerClient, element_guid: str, keywords: list[str]):
544
+ """Add a search keyword to an element. Throw an exception if a problem is encountered.
545
+
546
+ Args:
547
+ client (ServerClient): The Egeria client instance.
548
+ element_guid (str): The GUID of the element to add the keyword to.
549
+ keyword (str): The search keyword to add.
550
+
551
+ Returns:
552
+ None
553
+ """
554
+ try:
555
+ for keyword in keywords:
556
+ client.add_search_keyword_to_element(element_guid, keyword)
557
+ print("Added keyword `{}` to element `{}`".format(keyword, element_guid))
558
+
559
+ except PyegeriaException as e:
560
+ context = {
561
+ "readon" : "Exception encountered executing add_search_keyword",
562
+ "element_guid": element_guid,
563
+ "keyword": keyword,
564
+ "exception": str(e)
565
+ }
566
+ raise PyegeriaException(context = context)
567
+
568
+ def add_note_in_dr_e(client: ServerClient, qualified_name: str, display_name: str, journal_entry: str)-> str:
569
+ if journal_entry:
570
+ note_log_qn = f"{qualified_name}-NoteLog"
571
+ note_log_display_name = f"{display_name}-NoteLog"
572
+ note_display_name = f"{qualified_name}-Journal-Entry-{datetime.now().strftime('%Y-%m-%d %H:%M')}"
573
+ journal_entry_guid = client.add_journal_entry(note_log_qn, qualified_name, note_log_display_name,
574
+ note_display_name, journal_entry)
575
+ logger.info(f"Added journal entry `{journal_entry_guid}` to `{qualified_name}`")
576
+ return journal_entry_guid
577
+ else:
578
+ return None
@@ -0,0 +1,103 @@
1
+ """
2
+ Determines the width of a markdown table
3
+ """
4
+
5
+ import re
6
+ import html
7
+ from wcwidth import wcswidth
8
+
9
+ def split_row(line: str) -> list[str]:
10
+ s = line.strip()
11
+ if s.startswith("|"):
12
+ s = s[1:]
13
+ if s.endswith("|"):
14
+ s = s[:-1]
15
+
16
+ parts = []
17
+ cur = []
18
+ escape = False
19
+ for ch in s:
20
+ if escape:
21
+ cur.append(ch)
22
+ escape = False
23
+ elif ch == "\\":
24
+ escape = True
25
+ elif ch == "|":
26
+ parts.append("".join(cur))
27
+ cur = []
28
+ else:
29
+ cur.append(ch)
30
+ parts.append("".join(cur))
31
+ return parts
32
+
33
+ IMG_RE = re.compile(r'!\[([^\]]*)\]\([^)]+\)')
34
+ LINK_RE = re.compile(r'\[([^\]]*)\]\([^)]+\)')
35
+ CODE_TICKS_RE = re.compile(r'`([^`]*)`')
36
+ EMPH_RE = re.compile(r'(\*\*|\*|__|_)')
37
+
38
+ def visible_text(md: str) -> str:
39
+ s = md
40
+ s = IMG_RE.sub(lambda m: m.group(1), s) # images → alt
41
+ s = LINK_RE.sub(lambda m: m.group(1), s) # links → text
42
+ s = CODE_TICKS_RE.sub(lambda m: m.group(1), s) # remove backticks
43
+ s = EMPH_RE.sub("", s) # remove emphasis markers
44
+
45
+ # unescape common backslash-escapes
46
+ s = (s
47
+ .replace("\\|", "|")
48
+ .replace("\\*", "*")
49
+ .replace("\\_", "_")
50
+ .replace("\\`", "`")
51
+ .replace("\\\\", "\\"))
52
+
53
+ s = html.unescape(s) # &amp; → &
54
+ return s.strip()
55
+
56
+ def is_alignment_row(line: str) -> bool:
57
+ parts = split_row(line)
58
+ if not parts:
59
+ return False
60
+ def is_align_cell(c: str) -> bool:
61
+ c = c.strip()
62
+ return c != "" and all(ch in ":-" for ch in c)
63
+ return all(is_align_cell(p) for p in parts)
64
+
65
+ def column_widths(md_table: str) -> list[int]:
66
+ lines = [ln for ln in md_table.splitlines() if ln.strip()]
67
+ if not lines:
68
+ return []
69
+
70
+ lines_wo_align = [ln for ln in lines if not is_alignment_row(ln)]
71
+
72
+ rows = [split_row(ln) for ln in lines_wo_align]
73
+ if not rows:
74
+ return []
75
+
76
+ max_cols = max(len(r) for r in rows)
77
+ for r in rows:
78
+ if len(r) < max_cols:
79
+ r.extend([""] * (max_cols - len(r)))
80
+
81
+ widths = [0] * max_cols
82
+ for r in rows:
83
+ for i, cell in enumerate(r):
84
+ text = visible_text(cell)
85
+ w = wcswidth(text)
86
+ if w < 0: # non-printables fallback
87
+ w = len(text)
88
+ widths[i] = max(widths[i], w)
89
+ print(widths)
90
+ return widths
91
+
92
+ # Example usage
93
+ if __name__ == "__main__":
94
+ table = """
95
+ | Attribute Name | Input Required | Read Only | Generated | Default Value | Notes | Unique Values | Valid Values |
96
+ | ------------------- | -------------- | --------- | --------- | ------------- | ----------------------------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------- |
97
+ | Display Name | True | True | False | None | Name of the definition. | False | |
98
+ | Summary | False | True | False | None | Summary of the definition. | False | |
99
+ | Description | False | True | False | None | Description of the contents of the definition. | False | |
100
+ | Category | False | True | False | None | A user specified category name that can be used for example, to define product types or agreement types. | False | |
101
+ """
102
+
103
+ print(column_widths(table)) # e.g., [9, 28, 36] depending on characters
@@ -8,7 +8,7 @@ from md_processing.md_processing_utils.common_md_utils import (print_msg, find_k
8
8
  update_element_dictionary)
9
9
  from md_processing.md_processing_utils.message_constants import INFO, EXISTS_REQUIRED
10
10
  from md_processing.md_processing_utils.md_processing_constants import debug_level
11
- from pyegeria._globals import NO_ELEMENTS_FOUND
11
+ from pyegeria.core._globals import NO_ELEMENTS_FOUND
12
12
  from pyegeria.egeria_tech_client import EgeriaTech
13
13
 
14
14
 
@@ -74,45 +74,96 @@ def extract_command(block: str) -> str | None:
74
74
  return None
75
75
 
76
76
 
77
- def extract_attribute(text: str, labels: set) -> str | None:
77
+ # def extract_attribute(text: str, labels: set) -> str | None:
78
+ # """
79
+ # Extracts the attribute value from a string.
80
+ #
81
+ # Args:
82
+ # text: The input string.
83
+ # labels: List of equivalent labels to search for
84
+ #
85
+ # Returns:
86
+ # The value of the attribute, or None if not found.
87
+ #
88
+ # Note:
89
+ # Lines beginning with '>' are ignored.
90
+ # """
91
+ # # Iterate over the list of labels
92
+ # for label in labels:
93
+ # # Construct pattern for the current label
94
+ # # text = re.sub(r'\s+', ' ', text).strip() # just added
95
+ # # text = re.sub(r'\n\n+', '\n\n', text).strip()
96
+ #
97
+ # # Replace multiple spaces or tabs with a single space
98
+ # normalized = re.sub(r'\s+', ' ', text)
99
+ # # Collapse multiple blank lines into a single one
100
+ # normalized = re.sub(r'\n\s*\n', '\n', normalized).strip()
101
+ #
102
+ # # label = label.strip()
103
+ # # pattern = rf"##\s*{re.escape(label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
104
+ # # Normalize the label
105
+ # normalized_label = re.sub(r'\s+', ' ', label.strip())
106
+ #
107
+ # # Construct the regex pattern
108
+ # pattern = rf"##\s*{re.escape(normalized_label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
109
+ # # pattern = rf"##\s+{re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
110
+ # match = re.search(pattern, text, re.DOTALL)
111
+ # if match:
112
+ # # Extract matched text
113
+ # matched_text = match.group(1)
114
+ #
115
+ # # Filter out lines beginning with '>'
116
+ # filtered_lines = [line for line in matched_text.split('\n') if not line.strip().startswith('>')]
117
+ # filtered_text = '\n'.join(filtered_lines)
118
+ #
119
+ # # Replace consecutive \n with a single \n
120
+ # extracted_text = re.sub(r'\n+', '\n', filtered_text)
121
+ # if not extracted_text.isspace() and extracted_text:
122
+ # return extracted_text.strip() # Return the cleaned text - I removed the title casing
123
+ #
124
+ # return None
125
+
126
+
127
+ from typing import Optional, List
128
+
129
+ def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
78
130
  """
79
- Extracts the attribute value from a string.
131
+ def extract_attribute(text: str, labels: List[str]) -> Optional[str]:
80
132
 
81
- Args:
82
- text: The input string.
83
- labels: List of equivalent labels to search for
133
+ Extracts the attribute value from a string while:
134
+ - Preserving single newlines within the matched text.
135
+ - Removing lines starting with '>'.
84
136
 
85
- Returns:
86
- The value of the attribute, or None if not found.
137
+ Args:
138
+ text: The input string containing labeled sections.
139
+ labels: List of equivalent labels to search for.
87
140
 
88
- Note:
89
- Lines beginning with '>' are ignored.
90
- """
91
- # Iterate over the list of labels
92
- for label in labels:
93
- # Construct pattern for the current label
94
- # text = re.sub(r'\s+', ' ', text).strip() # just added
95
- text = re.sub(r'\n\n+', '\n\n', text).strip()
141
+ Returns:
142
+ The cleaned value of the attribute, or None if not found.
143
+ """
96
144
 
97
- label = label.strip()
98
- pattern = rf"##\s*{re.escape(label)}\s*\n(?:\s*\n)*?(.*?)(?:#|___|$)"
99
145
 
100
- # pattern = rf"##\s+{re.escape(label)}\n(.*?)(?:#|___|$)" # modified from --- to enable embedded tables
101
- match = re.search(pattern, text, re.DOTALL)
146
+ for label in labels:
147
+ # Construct pattern for the current label - stops at next ##, ___ separator, or end of text
148
+ pattern = rf"## {re.escape(label)}\n(.*?)(?=^##|^_{3,}|\Z)"
149
+ match = re.search(pattern, text, re.DOTALL | re.MULTILINE)
102
150
  if match:
103
151
  # Extract matched text
104
- matched_text = match.group(1)
105
-
106
- # Filter out lines beginning with '>'
107
- filtered_lines = [line for line in matched_text.split('\n') if not line.strip().startswith('>')]
108
- filtered_text = '\n'.join(filtered_lines)
152
+ extracted_text = match.group(1)
153
+
154
+ # Remove lines starting with '>' and lines that are only underscores/whitespace
155
+ filtered_lines = [
156
+ line for line in extracted_text.splitlines()
157
+ if not line.lstrip().startswith(">") and not re.match(r'^\s*_+\s*$', line)
158
+ ]
159
+ # Join the lines back, preserving single newlines
160
+ cleaned_text = "\n".join(filtered_lines).strip()
161
+
162
+ if cleaned_text:
163
+ return cleaned_text # Return the cleaned and formatted text
164
+ return None
109
165
 
110
- # Replace consecutive \n with a single \n
111
- extracted_text = re.sub(r'\n+', '\n', filtered_text)
112
- if not extracted_text.isspace() and extracted_text:
113
- return extracted_text.strip() # Return the cleaned text - I removed the title casing
114
166
 
115
- return None
116
167
 
117
168
 
118
169
  def process_simple_attribute(txt: str, labels: set, if_missing: str = INFO) -> str | None:
@@ -142,7 +193,7 @@ def process_simple_attribute(txt: str, labels: set, if_missing: str = INFO) -> s
142
193
  msg = f"Missing attribute with labels `{labels}` "
143
194
  print_msg(if_missing, msg, debug_level)
144
195
  return None
145
- return attribute
196
+ return attribute.strip()
146
197
 
147
198
 
148
199
  # def process_simple_attribute(txt: str, labels: list[str], if_missing: str = INFO) -> str | None:
@@ -412,8 +463,11 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str) ->
412
463
  return q_name, guid, unique, exists
413
464
 
414
465
  # Haven't seen this element before
415
- property_names = ['qualifiedName', 'name', 'displayName', 'title']
416
- open_metadata_type_name = None
466
+ property_names = ['qualifiedName', 'displayName', 'title']
467
+ if element_type == "InformalTag":
468
+ open_metadata_type_name = element_type
469
+ else:
470
+ open_metadata_type_name = None
417
471
  details = egeria_client.get_elements_by_property_value(element_name, property_names, open_metadata_type_name)
418
472
  if isinstance(details, str):
419
473
  msg = f"{element_type} `{element_name}` not found in Egeria"
@@ -421,12 +475,19 @@ def get_element_by_name(egeria_client, element_type: str, element_name: str) ->
421
475
  exists = False
422
476
  return None, None, unique, exists
423
477
  if len(details) > 1:
424
- msg = (f"More than one element with name {element_name} found, please specify a "
425
- f"**Qualified Name**")
426
- print_msg("DEBUG-ERROR", msg, debug_level)
427
- unique = False
428
- exists = None
429
- return element_name, None, unique, exists
478
+ if q_name is None:
479
+ q_name = egeria_client.__create_qualified_name__(element_type, element_name)
480
+ guid = egeria_client.__get_guid__(qualified_name=q_name)
481
+ update_element_dictionary(q_name, {'guid': guid})
482
+ exists = True if guid != "No elements found" else False
483
+ return q_name, guid, unique, exists
484
+ else:
485
+ msg = (f"More than one element with name {element_name} found, please specify a "
486
+ f"**Qualified Name**")
487
+ print_msg("DEBUG-ERROR", msg, debug_level)
488
+ unique = False
489
+ exists = None
490
+ return element_name, None, unique, exists
430
491
 
431
492
  el_qname = details[0]["properties"].get('qualifiedName', None)
432
493
  el_guid = details[0]['elementHeader']['guid']