pyegeria 5.3.9.9.3__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 (272) hide show
  1. commands/__init__.py +24 -0
  2. commands/cat/Dr-Egeria_md-orig.py +2 -2
  3. commands/cat/__init__.py +1 -17
  4. commands/cat/collection_actions.py +197 -0
  5. commands/cat/dr_egeria_command_help.py +372 -0
  6. commands/cat/dr_egeria_jupyter.py +7 -7
  7. commands/cat/dr_egeria_md.py +27 -182
  8. commands/cat/exp_list_glossaries.py +11 -14
  9. commands/cat/get_asset_graph.py +37 -267
  10. commands/cat/{get_collection.py → get_collection_tree.py} +10 -18
  11. commands/cat/get_project_dependencies.py +14 -14
  12. commands/cat/get_project_structure.py +15 -14
  13. commands/cat/get_tech_type_elements.py +16 -116
  14. commands/cat/glossary_actions.py +145 -298
  15. commands/cat/list_assets.py +3 -11
  16. commands/cat/list_cert_types.py +17 -63
  17. commands/cat/list_collections.py +46 -138
  18. commands/cat/list_deployed_catalogs.py +15 -27
  19. commands/cat/list_deployed_database_schemas.py +27 -43
  20. commands/cat/list_deployed_databases.py +16 -31
  21. commands/cat/list_deployed_servers.py +35 -54
  22. commands/cat/list_glossaries.py +18 -17
  23. commands/cat/list_projects.py +10 -12
  24. commands/cat/list_tech_type_elements.py +21 -37
  25. commands/cat/list_tech_types.py +13 -25
  26. commands/cat/list_terms.py +38 -79
  27. commands/cat/list_todos.py +4 -11
  28. commands/cat/list_user_ids.py +3 -10
  29. commands/cat/my_reports.py +559 -0
  30. commands/cat/run_report.py +394 -0
  31. commands/cat/run_report_orig.py +528 -0
  32. commands/cli/egeria.py +222 -247
  33. commands/cli/egeria_cat.py +68 -81
  34. commands/cli/egeria_my.py +13 -0
  35. commands/cli/egeria_ops.py +69 -74
  36. commands/cli/egeria_tech.py +17 -93
  37. commands/cli/ops_config.py +3 -6
  38. commands/{cat/list_categories.py → deprecated/list_data_designer.py} +53 -64
  39. commands/{cat/list_data_structures.py → deprecated/list_data_structures_full.py} +3 -6
  40. commands/deprecated/old_get_asset_graph.py +315 -0
  41. commands/my/__init__.py +0 -2
  42. commands/my/list_my_profile.py +27 -34
  43. commands/my/list_my_roles.py +1 -7
  44. commands/my/monitor_my_todos.py +1 -7
  45. commands/my/monitor_open_todos.py +6 -7
  46. commands/my/todo_actions.py +4 -5
  47. commands/ops/__init__.py +0 -2
  48. commands/ops/gov_server_actions.py +17 -21
  49. commands/ops/list_archives.py +17 -38
  50. commands/ops/list_catalog_targets.py +33 -40
  51. commands/ops/load_archive.py +35 -26
  52. commands/ops/{monitor_engine_activity_c.py → monitor_active_engine_activity.py} +51 -82
  53. commands/ops/{monitor_integ_daemon_status.py → monitor_daemon_status.py} +35 -55
  54. commands/ops/monitor_engine_activity.py +79 -77
  55. commands/ops/{monitor_gov_eng_status.py → monitor_engine_status.py} +10 -7
  56. commands/ops/monitor_platform_status.py +38 -50
  57. commands/ops/monitor_server_startup.py +6 -11
  58. commands/ops/monitor_server_status.py +7 -11
  59. commands/ops/orig_monitor_server_list.py +8 -8
  60. commands/ops/orig_monitor_server_status.py +1 -5
  61. commands/ops/refresh_integration_daemon.py +5 -5
  62. commands/ops/restart_integration_daemon.py +5 -5
  63. commands/ops/table_integ_daemon_status.py +6 -6
  64. commands/ops/x_engine_actions.py +7 -7
  65. commands/tech/__init__.py +0 -2
  66. commands/tech/{generic_actions.py → element_actions.py} +6 -11
  67. commands/tech/get_element_info.py +20 -29
  68. commands/tech/get_guid_info.py +23 -42
  69. commands/tech/get_tech_details.py +20 -35
  70. commands/tech/get_tech_type_template.py +28 -39
  71. commands/tech/list_all_om_type_elements.py +24 -30
  72. commands/tech/list_all_om_type_elements_x.py +22 -28
  73. commands/tech/list_all_related_elements.py +19 -28
  74. commands/tech/list_anchored_elements.py +22 -30
  75. commands/tech/list_asset_types.py +19 -24
  76. commands/tech/list_elements_by_classification_by_property_value.py +26 -32
  77. commands/tech/list_elements_by_property_value.py +19 -25
  78. commands/tech/list_elements_by_property_value_x.py +20 -28
  79. commands/tech/list_elements_for_classification.py +28 -41
  80. commands/tech/list_gov_action_processes.py +16 -27
  81. commands/tech/list_information_supply_chains.py +22 -30
  82. commands/tech/list_registered_services.py +14 -26
  83. commands/tech/list_related_elements_with_prop_value.py +15 -25
  84. commands/tech/list_related_specification.py +1 -4
  85. commands/tech/list_relationship_types.py +15 -25
  86. commands/tech/list_relationships.py +20 -36
  87. commands/tech/list_solution_blueprints.py +28 -33
  88. commands/tech/list_solution_components.py +23 -29
  89. commands/tech/list_solution_roles.py +21 -32
  90. commands/tech/list_tech_templates.py +51 -54
  91. commands/tech/list_valid_metadata_values.py +5 -9
  92. commands/tech/table_tech_templates.py +2 -6
  93. commands/tech/x_list_related_elements.py +1 -4
  94. examples/GeoSpatial Products Example.py +524 -0
  95. examples/Jupyter Notebooks/P-egeria-server-config.ipynb +2137 -0
  96. examples/Jupyter Notebooks/README.md +2 -0
  97. examples/Jupyter Notebooks/common/P-environment-check.ipynb +115 -0
  98. examples/Jupyter Notebooks/common/__init__.py +14 -0
  99. examples/Jupyter Notebooks/common/common-functions.ipynb +4694 -0
  100. examples/Jupyter Notebooks/common/environment-check.ipynb +52 -0
  101. examples/Jupyter Notebooks/common/globals.ipynb +184 -0
  102. examples/Jupyter Notebooks/common/globals.py +154 -0
  103. examples/Jupyter Notebooks/common/orig_globals.py +152 -0
  104. examples/format_sets/all_format_sets.json +910 -0
  105. examples/format_sets/custom_format_sets.json +268 -0
  106. examples/format_sets/subset_format_sets.json +187 -0
  107. examples/format_sets_save_load_example.py +291 -0
  108. examples/jacquard_data_sets.py +129 -0
  109. examples/output_formats_example.py +193 -0
  110. examples/test_jacquard_data_sets.py +54 -0
  111. examples/test_jacquard_data_sets_scenarios.py +94 -0
  112. md_processing/__init__.py +90 -0
  113. md_processing/command_dispatcher.py +33 -0
  114. md_processing/command_mapping.py +221 -0
  115. md_processing/data/commands/commands_data_designer.json +537 -0
  116. md_processing/data/commands/commands_external_reference.json +733 -0
  117. md_processing/data/commands/commands_feedback.json +155 -0
  118. md_processing/data/commands/commands_general.json +204 -0
  119. md_processing/data/commands/commands_glossary.json +218 -0
  120. md_processing/data/commands/commands_governance.json +3678 -0
  121. md_processing/data/commands/commands_product_manager.json +865 -0
  122. md_processing/data/commands/commands_project.json +642 -0
  123. md_processing/data/commands/commands_solution_architect.json +366 -0
  124. md_processing/data/commands.json +17568 -0
  125. md_processing/data/commands_working.json +30641 -0
  126. md_processing/data/gened_report_specs.py +6584 -0
  127. md_processing/data/generated_format_sets.json +6533 -0
  128. md_processing/data/generated_format_sets_old.json +4137 -0
  129. md_processing/data/generated_format_sets_old.py +45 -0
  130. md_processing/dr_egeria.py +182 -0
  131. md_processing/md_commands/__init__.py +3 -0
  132. md_processing/md_commands/data_designer_commands.py +1276 -0
  133. md_processing/md_commands/ext_ref_commands.py +530 -0
  134. md_processing/md_commands/feedback_commands.py +726 -0
  135. md_processing/md_commands/glossary_commands.py +684 -0
  136. md_processing/md_commands/governance_officer_commands.py +600 -0
  137. md_processing/md_commands/product_manager_commands.py +1266 -0
  138. md_processing/md_commands/project_commands.py +383 -0
  139. md_processing/md_commands/solution_architect_commands.py +1184 -0
  140. md_processing/md_commands/view_commands.py +295 -0
  141. md_processing/md_processing_utils/__init__.py +4 -0
  142. md_processing/md_processing_utils/common_md_proc_utils.py +1249 -0
  143. md_processing/md_processing_utils/common_md_utils.py +578 -0
  144. md_processing/md_processing_utils/determine_width.py +103 -0
  145. md_processing/md_processing_utils/extraction_utils.py +547 -0
  146. md_processing/md_processing_utils/gen_report_specs.py +643 -0
  147. md_processing/md_processing_utils/generate_dr_help.py +193 -0
  148. md_processing/md_processing_utils/generate_md_cmd_templates.py +144 -0
  149. md_processing/md_processing_utils/generate_md_templates.py +83 -0
  150. md_processing/md_processing_utils/md_processing_constants.py +1228 -0
  151. md_processing/md_processing_utils/message_constants.py +19 -0
  152. pyegeria/__init__.py +201 -443
  153. pyegeria/core/__init__.py +40 -0
  154. pyegeria/core/_base_platform_client.py +574 -0
  155. pyegeria/core/_base_server_client.py +573 -0
  156. pyegeria/core/_exceptions.py +457 -0
  157. pyegeria/core/_globals.py +60 -0
  158. pyegeria/core/_server_client.py +6073 -0
  159. pyegeria/core/_validators.py +257 -0
  160. pyegeria/core/config.py +654 -0
  161. pyegeria/{create_tech_guid_lists.py → core/create_tech_guid_lists.py} +0 -1
  162. pyegeria/core/load_config.py +37 -0
  163. pyegeria/core/logging_configuration.py +207 -0
  164. pyegeria/core/mcp_adapter.py +144 -0
  165. pyegeria/core/mcp_server.py +212 -0
  166. pyegeria/core/utils.py +405 -0
  167. pyegeria/deprecated/__init__.py +0 -0
  168. pyegeria/{_client.py → deprecated/_client.py} +62 -24
  169. pyegeria/{_deprecated_gov_engine.py → deprecated/_deprecated_gov_engine.py} +16 -16
  170. pyegeria/{classification_manager_omvs.py → deprecated/classification_manager_omvs.py} +1988 -1878
  171. pyegeria/deprecated/output_formatter_with_machine_keys.py +1127 -0
  172. pyegeria/{runtime_manager_omvs.py → deprecated/runtime_manager_omvs.py} +216 -229
  173. pyegeria/{valid_metadata_omvs.py → deprecated/valid_metadata_omvs.py} +93 -93
  174. pyegeria/{x_action_author_omvs.py → deprecated/x_action_author_omvs.py} +2 -3
  175. pyegeria/egeria_cat_client.py +25 -51
  176. pyegeria/egeria_client.py +140 -98
  177. pyegeria/egeria_config_client.py +48 -24
  178. pyegeria/egeria_tech_client.py +170 -83
  179. pyegeria/models/__init__.py +150 -0
  180. pyegeria/models/collection_models.py +168 -0
  181. pyegeria/models/models.py +654 -0
  182. pyegeria/omvs/__init__.py +84 -0
  183. pyegeria/omvs/action_author.py +342 -0
  184. pyegeria/omvs/actor_manager.py +5980 -0
  185. pyegeria/omvs/asset_catalog.py +842 -0
  186. pyegeria/omvs/asset_maker.py +2736 -0
  187. pyegeria/omvs/automated_curation.py +4403 -0
  188. pyegeria/omvs/classification_manager.py +11213 -0
  189. pyegeria/omvs/collection_manager.py +5780 -0
  190. pyegeria/omvs/community_matters_omvs.py +468 -0
  191. pyegeria/{core_omag_server_config.py → omvs/core_omag_server_config.py} +157 -157
  192. pyegeria/{data_designer_omvs.py → omvs/data_designer.py} +1991 -1691
  193. pyegeria/omvs/data_discovery.py +869 -0
  194. pyegeria/omvs/data_engineer.py +372 -0
  195. pyegeria/omvs/digital_business.py +1133 -0
  196. pyegeria/omvs/external_links.py +1752 -0
  197. pyegeria/omvs/feedback_manager.py +834 -0
  198. pyegeria/{full_omag_server_config.py → omvs/full_omag_server_config.py} +73 -69
  199. pyegeria/omvs/glossary_manager.py +3231 -0
  200. pyegeria/omvs/governance_officer.py +3009 -0
  201. pyegeria/omvs/lineage_linker.py +314 -0
  202. pyegeria/omvs/location_arena.py +1525 -0
  203. pyegeria/omvs/metadata_expert.py +668 -0
  204. pyegeria/omvs/metadata_explorer_omvs.py +2943 -0
  205. pyegeria/omvs/my_profile.py +1042 -0
  206. pyegeria/omvs/notification_manager.py +358 -0
  207. pyegeria/omvs/people_organizer.py +394 -0
  208. pyegeria/{platform_services.py → omvs/platform_services.py} +113 -193
  209. pyegeria/omvs/product_manager.py +1825 -0
  210. pyegeria/omvs/project_manager.py +1907 -0
  211. pyegeria/omvs/reference_data.py +1140 -0
  212. pyegeria/omvs/registered_info.py +334 -0
  213. pyegeria/omvs/runtime_manager.py +2817 -0
  214. pyegeria/omvs/schema_maker.py +446 -0
  215. pyegeria/{server_operations.py → omvs/server_operations.py} +27 -26
  216. pyegeria/omvs/solution_architect.py +6490 -0
  217. pyegeria/omvs/specification_properties.py +37 -0
  218. pyegeria/omvs/subject_area.py +1042 -0
  219. pyegeria/omvs/template_manager_omvs.py +236 -0
  220. pyegeria/omvs/time_keeper.py +1761 -0
  221. pyegeria/omvs/valid_metadata.py +3221 -0
  222. pyegeria/omvs/valid_metadata_lists.py +37 -0
  223. pyegeria/omvs/valid_type_lists.py +37 -0
  224. pyegeria/view/__init__.py +28 -0
  225. pyegeria/view/_output_format_models.py +514 -0
  226. pyegeria/view/_output_formats.py +14 -0
  227. pyegeria/view/base_report_formats.py +2719 -0
  228. pyegeria/view/dr_egeria_reports.py +56 -0
  229. pyegeria/view/format_set_executor.py +397 -0
  230. pyegeria/{md_processing_utils.py → view/md_processing_utils.py} +5 -5
  231. pyegeria/{mermaid_utilities.py → view/mermaid_utilities.py} +2 -154
  232. pyegeria/view/output_formatter.py +1297 -0
  233. pyegeria-5.5.3.3.dist-info/METADATA +218 -0
  234. pyegeria-5.5.3.3.dist-info/RECORD +241 -0
  235. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info}/WHEEL +2 -1
  236. pyegeria-5.5.3.3.dist-info/entry_points.txt +103 -0
  237. pyegeria-5.5.3.3.dist-info/top_level.txt +4 -0
  238. commands/cat/.DS_Store +0 -0
  239. commands/cat/README.md +0 -16
  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/monitor_asset_events.py +0 -108
  244. commands/tech/README.md +0 -24
  245. pyegeria/.DS_Store +0 -0
  246. pyegeria/README.md +0 -35
  247. pyegeria/_globals.py +0 -47
  248. pyegeria/_validators.py +0 -385
  249. pyegeria/asset_catalog_omvs.py +0 -864
  250. pyegeria/automated_curation_omvs.py +0 -3765
  251. pyegeria/collection_manager_omvs.py +0 -2744
  252. pyegeria/dr.egeria spec.md +0 -9
  253. pyegeria/egeria_my_client.py +0 -56
  254. pyegeria/feedback_manager_omvs.py +0 -4573
  255. pyegeria/glossary_browser_omvs.py +0 -3728
  256. pyegeria/glossary_manager_omvs.py +0 -2440
  257. pyegeria/m_test.py +0 -118
  258. pyegeria/md_processing_helpers.py +0 -58
  259. pyegeria/md_processing_utils_orig.py +0 -1103
  260. pyegeria/metadata_explorer_omvs.py +0 -2326
  261. pyegeria/my_profile_omvs.py +0 -1022
  262. pyegeria/output_formatter.py +0 -389
  263. pyegeria/project_manager_omvs.py +0 -1933
  264. pyegeria/registered_info.py +0 -167
  265. pyegeria/solution_architect_omvs.py +0 -2156
  266. pyegeria/template_manager_omvs.py +0 -1414
  267. pyegeria/utils.py +0 -197
  268. pyegeria-5.3.9.9.3.dist-info/METADATA +0 -72
  269. pyegeria-5.3.9.9.3.dist-info/RECORD +0 -143
  270. pyegeria-5.3.9.9.3.dist-info/entry_points.txt +0 -99
  271. /pyegeria/{_exceptions.py → deprecated/_exceptions.py} +0 -0
  272. {pyegeria-5.3.9.9.3.dist-info → pyegeria-5.5.3.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,528 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ SPDX-License-Identifier: Apache-2.0
4
+ Copyright Contributors to the ODPi Egeria project.
5
+
6
+ A command that takes an output format set name, looks up the format set using select_report_spec,
7
+ and invokes the specified function with parameters filled from command line arguments.
8
+
9
+ This command works with any format set defined in output_formatter.py that has an "action" property.
10
+ It dynamically determines the appropriate client class and method to call based on the format set,
11
+ and prompts for any required parameters that aren't provided on the command line.
12
+
13
+ Features:
14
+ - Works with any format set that has an "action" property
15
+ - Dynamically adds command-line arguments based on the format set's required/optional parameters
16
+ - Prompts for required parameters if not provided
17
+ - Supports multiple output formats (TABLE, DICT, FORM, REPORT, HTML, LIST)
18
+ - Handles both instance methods and standalone functions
19
+ - Provides informative error messages
20
+
21
+ Examples:
22
+ # List all collections using the Collections format set
23
+ format_set_action --format-set Collections --search-string "*" --output-format TABLE
24
+
25
+ # Output collections in DICT format
26
+ format_set_action --format-set Collections --search-string "*" --output-format DICT
27
+
28
+ # Use a specific search string
29
+ format_set_action --format-set Collections --search-string "Data*" --output-format TABLE
30
+
31
+ # Use a different format set (Data Dictionary)
32
+ format_set_action --format-set "Data Dictionary" --search-string "*" --output-format TABLE
33
+
34
+ # Use a format set with multiple parameters (will prompt for missing parameters)
35
+ format_set_action --format-set DigitalProducts --output-format REPORT
36
+ """
37
+ import argparse
38
+ import json
39
+ import os
40
+ import time
41
+
42
+ from loguru import logger
43
+ from pydantic import ValidationError
44
+ from rich import box
45
+ from rich.console import Console
46
+ from rich.markdown import Markdown
47
+ from rich.prompt import Prompt
48
+ from rich.table import Table
49
+
50
+ from pyegeria import (
51
+ EgeriaTech,
52
+ CollectionManager,
53
+ NO_ELEMENTS_FOUND, GovernanceOfficer, GlossaryManager, print_validation_error,
54
+ )
55
+ from pyegeria.core.config import settings
56
+ from pyegeria.omvs.external_links import ExternalReferences
57
+ from pyegeria.core.logging_configuration import config_logging
58
+ from pyegeria.view.base_report_formats import (select_report_format)
59
+ from pyegeria.core._exceptions import PyegeriaException, print_exception_response
60
+
61
+ # pydevd_pycharm.settrace('host.docker.internal', # Use 'host.docker.internal' to connect to the host machine
62
+ # port=5678, # Port to communicate with PyCharm
63
+ # stdoutToServer=True, # Forward stdout to PyCharm
64
+ # stderrToServer=True, # Forward stderr to PyCharm
65
+ # suspend=True) # Suspend execution until the debugger is connected
66
+ #
67
+
68
+
69
+ EGERIA_USER = os.environ.get("EGERIA_USER", "erinoverview")
70
+ EGERIA_USER_PASSWORD = os.environ.get("EGERIA_USER_PASSWORD", "secret")
71
+
72
+
73
+ app_config = settings.Environment
74
+ config_logging()
75
+
76
+ print(f"Console width is {app_config.console_width}")
77
+ console = Console(
78
+ style="bold bright_white on black",
79
+ width=app_config.console_width,
80
+ force_terminal=not app_config.egeria_jupyter,
81
+ )
82
+
83
+ def execute_format_set_action(
84
+ format_set_name: str,
85
+ view_server: str = app_config.egeria_view_server,
86
+ view_url: str = app_config.egeria_view_server_url,
87
+ user: str = settings.User_Profile.user_name,
88
+ user_pass: str = settings.User_Profile.user_pwd,
89
+ output_format: str = "TABLE",
90
+ **kwargs
91
+ ):
92
+ """
93
+ Looks up the specified output format set, extracts the function and parameters,
94
+ and invokes the function with the parameters.
95
+
96
+ Parameters
97
+ ----------
98
+ format_set_name : str
99
+ The name of the output format set to use.
100
+ view_server : str
101
+ The view server name or address where the Egeria services are hosted.
102
+ view_url : str
103
+ The URL of the platform the view server is on.
104
+ user : str
105
+ The user ID for authentication with the Egeria server.
106
+ user_pass : str
107
+ The password for authentication with the Egeria server.
108
+ jupyter : bool, optional
109
+ A boolean indicating whether the output is intended for a Jupyter notebook.
110
+ width : int, optional
111
+ The width of the console output.
112
+ output_format : str, optional
113
+ Format of the output. Default is TABLE.
114
+ **kwargs : dict
115
+ Additional parameters to override the default parameters in the format set.
116
+ """
117
+ # Get the output format set
118
+ # logger.info(f"Entering execute_format_set_action, format set name: {format_set_name}, search_string: {kwargs.get('search_string',"meow")}")
119
+ # logger.info(json.dumps(kwargs, indent=2))
120
+ format_set = select_report_format(format_set_name, output_format)
121
+ if not format_set:
122
+ print(f"Error: Output format set '{format_set_name}' does not have a format compatible with output format '{output_format}'.")
123
+ return
124
+
125
+ # Check if the format set has an action property
126
+ if "action" not in format_set:
127
+ print(f"Error: Output format set '{format_set_name}' does not have an action property.")
128
+ return
129
+
130
+ # Extract the function and parameters from the action property (now a dict)
131
+ action = format_set["action"]
132
+ func = action.get("function")
133
+ required_params = action.get("required_params", action.get("user_params", []))
134
+ optional_params = action.get("optional_params", [])
135
+ spec_params = action.get("spec_params", {})
136
+
137
+ # Create a params dictionary from required/optional and spec_params
138
+ params = {}
139
+ for param in required_params:
140
+ if param in kwargs and kwargs[param]:
141
+ params[param] = kwargs[param]
142
+ elif param not in kwargs and param not in spec_params:
143
+ print(f"Warning: Required parameter '{param}' not provided for format set '{format_set_name}'.")
144
+ for param in optional_params:
145
+ if param in kwargs and kwargs[param]:
146
+ params[param] = kwargs[param]
147
+
148
+ # Add spec_params to params
149
+ params.update(spec_params)
150
+
151
+ # Delegate execution to exec_report_spec for canonical behavior
152
+ from pyegeria.view.format_set_executor import exec_report_spec
153
+ ofmt = (output_format or "TABLE").upper()
154
+ mapped = "DICT" if ofmt == "TABLE" else ofmt
155
+ res = exec_report_spec(
156
+ format_set_name,
157
+ output_format=mapped,
158
+ params=params,
159
+ view_server=view_server,
160
+ view_url=view_url,
161
+ user=user,
162
+ user_pass=user_pass,
163
+ )
164
+
165
+ # Handle TABLE rendering locally
166
+ if ofmt == "TABLE":
167
+ if res.get("kind") != "json":
168
+ print("No results or unexpected response:", res)
169
+ return
170
+ data = res.get("data")
171
+ # Render basic table
172
+ table = Table(
173
+ title=f"{format_set_name} @ {time.asctime()}",
174
+ style="bright_white on black",
175
+ header_style="bright_white on dark_blue",
176
+ title_style="bold white on black",
177
+ caption_style="white on black",
178
+ show_lines=True,
179
+ box=box.ROUNDED,
180
+ caption=f"View Server '{view_server}' @ Platform - {view_url}",
181
+ expand=True,
182
+ )
183
+ rows = data if isinstance(data, list) else [data]
184
+ if rows and isinstance(rows[0], dict):
185
+ cols = list(rows[0].keys())
186
+ for c in cols:
187
+ table.add_column(str(c), justify="left", style="cyan")
188
+ for r in rows:
189
+ table.add_row(*[str(r.get(c, "")) for c in cols])
190
+ else:
191
+ table.add_column("Value")
192
+ for r in rows:
193
+ table.add_row(str(r))
194
+ # Optional header
195
+ from pyegeria.view.base_report_formats import get_report_format_heading, get_report_format_description
196
+ heading = get_report_format_heading(format_set_name)
197
+ desc = get_report_format_description(format_set_name)
198
+ if heading and desc:
199
+ console.print(Markdown(f"# {heading}\n{desc}\n"))
200
+ console.print(table)
201
+ return
202
+
203
+ # For non-table formats, write to file based on MIME/kind
204
+ kind = res.get("kind")
205
+ mime = res.get("mime")
206
+ out_dir = os.path.join(app_config.pyegeria_root, app_config.dr_egeria_outbox)
207
+ ts = time.strftime('%Y-%m-%d-%H-%M-%S')
208
+ safe_name = "".join(c for c in format_set_name if c.isalnum() or c in ("-","_","+","."," ")).strip().replace(" ", "_")
209
+
210
+ if kind == "text":
211
+ content = res.get("content", "")
212
+ ext = ".html" if mime == "text/html" else ".md"
213
+ elif kind == "json":
214
+ content = json.dumps(res.get("data"), indent=2)
215
+ ext = ".json"
216
+ else:
217
+ content = json.dumps(res, indent=2, default=str)
218
+ ext = ".txt"
219
+
220
+ file_name = f"{safe_name}-{ts}{ext}"
221
+ full_file_path = os.path.join(out_dir, file_name)
222
+ os.makedirs(os.path.dirname(full_file_path), exist_ok=True)
223
+ with open(full_file_path, "w", encoding="utf-8") as f:
224
+ f.write(content)
225
+ print(f"\n==> Output written to {full_file_path}")
226
+ if ext == ".html":
227
+ print(f"\n==> Web link: [{file_name}]({app_config.pyegeria_publishing_root}/{file_name})")
228
+ return
229
+
230
+ # Determine the appropriate client class based on the format set name or function
231
+ client_class = None
232
+ method_name = None
233
+
234
+ # If function name is provided as a string, parse it to get class and method
235
+ if isinstance(func, str) and "." in func:
236
+ class_name, method_name = func.split(".")
237
+ if class_name == "CollectionManager":
238
+ client_class = CollectionManager
239
+ elif class_name == "GovernanceOfficer":
240
+ client_class = GovernanceOfficer
241
+ elif class_name == "GlossaryManager":
242
+ client_class = GlossaryManager
243
+ elif class_name == "ExternalReference":
244
+ client_class = ExternalReferences
245
+ else:
246
+ client_class = EgeriaTech
247
+
248
+
249
+ # Add more client classes as needed
250
+
251
+ # # If client_class is still None, determine based on format set name
252
+ # if client_class is None:
253
+ # if format_set_name in ["Collections", "Data Dictionary", "Data Specification", "DigitalProducts"]:
254
+ # client_class = CollectionManager
255
+ # method_name = "find_collections"
256
+ # else:
257
+ # # Default to CollectionManager for now
258
+ # client_class = CollectionManager
259
+
260
+ # Create the client instance
261
+ client = client_class(view_server, view_url, user_id=user, user_pwd=user_pass)
262
+
263
+ # If method_name is set, get the method from the client
264
+ # Note: We need to convert func from string to method reference even if func is already set
265
+ if method_name:
266
+ if hasattr(client, method_name):
267
+ func = getattr(client, method_name)
268
+ else:
269
+ print(f"Error: Method '{method_name}' not found in client class '{client_class.__name__}'.")
270
+ return
271
+
272
+ # Check if we have a valid function to call
273
+ if not func and not method_name:
274
+ print(f"Error: No valid function found for format set '{format_set_name}'.")
275
+ return
276
+
277
+ client.create_egeria_bearer_token()
278
+
279
+ # Get heading and description information
280
+ heading = get_report_format_heading(format_set_name)
281
+ desc = get_report_format_description(format_set_name)
282
+ preamble = f"# {heading}\n{desc}\n\n" if heading and desc else ""
283
+
284
+ try:
285
+ # Invoke the function with the parameters
286
+ if output_format != "TABLE":
287
+ file_path = os.path.join(app_config.pyegeria_root, app_config.dr_egeria_outbox)
288
+ if output_format == "HTML":
289
+ file_name = f"{format_set_name}-{time.strftime('%Y-%m-%d-%H-%M-%S')}.html"
290
+ elif output_format == "JSON":
291
+ file_name = f"{format_set_name}-{time.strftime('%Y-%m-%d-%H-%M-%S')}.json"
292
+ elif output_format == "DICT":
293
+ file_name = f"{format_set_name}-{time.strftime('%Y-%m-%d-%H-%M-%S')}.py"
294
+ elif output_format == "MERMAID":
295
+ file_name = f"{format_set_name}-{time.strftime('%Y-%m-%d-%H-%M-%S')}.md"
296
+ else:
297
+ file_name = f"{format_set_name}-{time.strftime('%Y-%m-%d-%H-%M-%S')}.md"
298
+ full_file_path = os.path.join(file_path, file_name)
299
+ os.makedirs(os.path.dirname(full_file_path), exist_ok=True)
300
+
301
+ # Add output_format to params
302
+ params['output_format'] = output_format
303
+
304
+ # Call the function with the parameters
305
+ print(f"\n==> Calling function: {func} with parameters:{params}")
306
+ try:
307
+ if callable(func):
308
+ # Call the function as an instance method of the client
309
+ output = func(**params)
310
+ else:
311
+ # For standalone functions, call with client as first argument
312
+ output = func(client, **params)
313
+ except ValidationError as e:
314
+ print_validation_error(e)
315
+ return
316
+
317
+ except TypeError as e:
318
+ # Handle parameter mismatch errors
319
+ print(f"Error calling function: {e}")
320
+ print(f"Parameters provided: {params}")
321
+ return
322
+
323
+ if output == NO_ELEMENTS_FOUND:
324
+ print(f"\n==> No elements found for format set '{format_set_name}'")
325
+ return
326
+ elif isinstance(output, (str, list)) and output_format == "DICT":
327
+ output = json.dumps(output, indent=4)
328
+ elif isinstance(output, (str, list)) and output_format in[ "REPORT" ]:
329
+ output = preamble + output
330
+ elif isinstance(output, (str, list)) and output_format == "HTML":
331
+ pass
332
+
333
+ with open(full_file_path, 'w') as f:
334
+ f.write(output)
335
+ print(f"\n==> Output written to {full_file_path}")
336
+ if output_format == "HTML":
337
+ print(f"\n==> Web link: [{file_name}]({app_config.pyegeria_publishing_root}/{file_name}")
338
+ return
339
+ else:
340
+ # For TABLE output, add output_format to params
341
+ params['output_format'] = "TABLE"
342
+ print(f"\n==> Calling function: {func} with parameters:{params}")
343
+ # Call the function and create a table
344
+ try:
345
+ if hasattr(client, method_name): # It's a method of the client
346
+ # Call the function as an instance method of the client
347
+ result = func(**params)
348
+ else:
349
+ # For standalone functions, call with client as first argument
350
+ result = func(client, **params)
351
+ except TypeError as e:
352
+ # Handle parameter mismatch errors
353
+ print(f"Error calling function: {e}")
354
+ print(f"Parameters provided: {params}")
355
+ return
356
+
357
+ if not result or result == NO_ELEMENTS_FOUND:
358
+ print(f"\n==> No elements found for format set '{format_set_name}'")
359
+ return
360
+
361
+
362
+ if heading and desc:
363
+ console.print(Markdown(preamble))
364
+
365
+ # Create a table for the results
366
+ table = Table(
367
+ title=f"{format_set_name} @ {time.asctime()}",
368
+ style="bright_white on black",
369
+ header_style="bright_white on dark_blue",
370
+ title_style="bold white on black",
371
+ caption_style="white on black",
372
+ show_lines=True,
373
+ box=box.ROUNDED,
374
+ caption=f"View Server '{view_server}' @ Platform - {view_url}",
375
+ expand=True,
376
+ )
377
+
378
+ # Handle both list and dictionary results
379
+ if isinstance(result, list):
380
+ if not result:
381
+ print(f"\n==> No elements found for format set '{format_set_name}'")
382
+ return
383
+
384
+ # Sort the results by display_name if available
385
+ if result[0].get("display_name", None):
386
+ sorted_results = sorted(result, key=lambda k: k.get("display_name", ""))
387
+ elif result[0].get("Display Name", None):
388
+ sorted_results = sorted(result, key=lambda k: k.get("Display Name", ""))
389
+ else:
390
+ sorted_results = result
391
+
392
+ # Add columns dynamically based on the first result
393
+ column_headings = list(sorted_results[0].keys())
394
+ for heading in column_headings:
395
+ if heading == "Usage":
396
+ table.add_column(heading, justify="left", style="cyan")
397
+ else:
398
+ table.add_column(heading, justify="left", style="cyan")
399
+
400
+ # Add rows
401
+ for item in sorted_results:
402
+ row_values = []
403
+ for key in column_headings:
404
+ value = item.get(key, "")
405
+ row_values.append(str(value))
406
+
407
+ table.add_row(*row_values)
408
+ else:
409
+ # Handle single dictionary result
410
+ column_headings = list(result.keys())
411
+ for heading in column_headings:
412
+ table.add_column(heading, justify="left", style="cyan")
413
+
414
+ row_values = []
415
+ for key in column_headings:
416
+ value = result.get(key, "")
417
+ row_values.append(str(value))
418
+
419
+ table.add_row(*row_values)
420
+
421
+ # Print the table
422
+
423
+ console.print(table)
424
+
425
+ except PyegeriaException as e:
426
+ print_exception_response(e)
427
+ finally:
428
+ client.close_session()
429
+
430
+
431
+ def main():
432
+ # First, parse just the format-set argument to determine which other arguments to add
433
+ logger.enable("pyegeria")
434
+ initial_parser = argparse.ArgumentParser(add_help=False)
435
+ initial_parser.add_argument("--report", help="Name of the report spec", required=True)
436
+ initial_args, _ = initial_parser.parse_known_args()
437
+
438
+ # Get the format set to determine parameters
439
+ format_set_name = initial_args.report
440
+ format_set = select_report_format(format_set_name, "ANY")
441
+
442
+ # Check if the format set exists
443
+ if not format_set:
444
+ print(f"Error: Report Spec for '{format_set_name}' not found.")
445
+ print("Available Report Specs:")
446
+ from pyegeria.view.base_report_formats import report_spec_list
447
+ for name in report_spec_list():
448
+ print(f" - {name}")
449
+ return
450
+
451
+ # Create the full parser with all arguments
452
+ parser = argparse.ArgumentParser(description="Execute an action from Report Spec")
453
+ parser.add_argument("--report", help="Name of the report spec", required=True)
454
+ parser.add_argument("--server", help="Name of the server to connect to")
455
+ parser.add_argument("--url", help="URL Platform to connect to")
456
+ parser.add_argument("--userid", help="User Id")
457
+ parser.add_argument("--password", help="User Password")
458
+ parser.add_argument("--output-format", help="Output format (TABLE, DICT, FORM, REPORT, HTML, LIST)",
459
+ choices=["TABLE", "DICT", "FORM", "REPORT", "HTML", "LIST", "MERMAID"], default="TABLE")
460
+
461
+
462
+
463
+ # Add arguments based on the format set's required/optional params
464
+ required_params = []
465
+ optional_params = []
466
+ if "action" in format_set:
467
+ action = format_set["action"]
468
+ required_params = action.get("required_params", action.get("user_params", []))
469
+ optional_params = action.get("optional_params", [])
470
+
471
+ for param in sorted(set(required_params + optional_params)):
472
+ parser.add_argument(f"--{param.replace('_', '-')}", help=f"{param.replace('_', ' ')} parameter")
473
+ else:
474
+ print(f"Error: Report Spec '{format_set_name}' does not have an action property.")
475
+ return
476
+
477
+ args = parser.parse_args()
478
+ app_settings = settings
479
+ app_config = app_settings.Environment
480
+
481
+ server = args.server if args.server is not None else app_config.egeria_view_server
482
+ url = args.url if args.url is not None else app_config.egeria_view_server_url
483
+ print(f"root path: {app_config.pyegeria_root}, config_file: {app_config.pyegeria_config_file}")
484
+ userid = args.userid if args.userid is not None else EGERIA_USER
485
+ user_pass = args.password if args.password is not None else EGERIA_USER_PASSWORD
486
+ format_set_name = args.report
487
+ output_format = args.output_format
488
+
489
+ logger.info(f"view server @ {url}")
490
+ # Collect all parameters from args
491
+ kwargs = {}
492
+ for param in sorted(set(required_params + optional_params)):
493
+ arg_name = param.replace('_', '-')
494
+ if hasattr(args, arg_name) and getattr(args, arg_name) is not None:
495
+ kwargs[param] = getattr(args, arg_name)
496
+ elif hasattr(args, param) and getattr(args, param) is not None:
497
+ kwargs[param] = getattr(args, param)
498
+
499
+ try:
500
+ # If a required parameter is not provided, prompt for it
501
+ for param in required_params:
502
+ if param not in kwargs:
503
+ default_value = "*" if param == "search_string" else ""
504
+ prompt_text = f"Enter {param.replace('_', ' ')}:"
505
+ if default_value:
506
+ prompt_text += f" (default: {default_value})"
507
+ value = Prompt.ask(prompt_text, default=default_value).strip()
508
+ kwargs[param] = value
509
+ print(f"Using Report Spec {format_set_name} and output format {output_format} with parameters: {kwargs} ")
510
+ execute_format_set_action(
511
+ format_set_name=format_set_name,
512
+ view_server=server,
513
+ view_url=url,
514
+ user=userid,
515
+ user_pass=user_pass,
516
+ output_format=output_format,
517
+ **kwargs
518
+ )
519
+
520
+ except KeyboardInterrupt:
521
+ pass
522
+
523
+ except PyegeriaException as e:
524
+ print_exception_response(e)
525
+
526
+
527
+ if __name__ == "__main__":
528
+ main()