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,37 @@
1
+ """
2
+ PDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ This module contains the Valid Metadata Lists View Service client.
6
+ """
7
+
8
+ from pyegeria.omvs.valid_metadata import ValidMetadataManager
9
+ from typing import Any, Optional
10
+
11
+ class ValidMetadataLists(ValidMetadataManager):
12
+ """
13
+ Client for the Valid Metadata Lists View Service.
14
+ This is a specialized version of the Valid Metadata Manager focusing on metadata lists.
15
+
16
+ Attributes
17
+ ----------
18
+ view_server : str
19
+ The name of the View Server to use.
20
+ platform_url : str
21
+ URL of the server platform to connect to.
22
+ user_id : str
23
+ The identity of the user calling the method.
24
+ user_pwd : str
25
+ The password associated with the user_id. Defaults to None.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ view_server: str,
31
+ platform_url: str,
32
+ user_id: str,
33
+ user_pwd: Optional[str] = None,
34
+ token: Optional[str] = None,
35
+ ):
36
+ super().__init__(view_server, platform_url, user_id, user_pwd, token)
37
+ self.url_marker = "valid-metadata"
@@ -0,0 +1,37 @@
1
+ """
2
+ PDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ This module contains the Valid Type Lists View Service client.
6
+ """
7
+
8
+ from pyegeria.omvs.valid_metadata import ValidMetadataManager
9
+ from typing import Any, Optional
10
+
11
+ class ValidTypeLists(ValidMetadataManager):
12
+ """
13
+ Client for the Valid Type Lists View Service.
14
+ This is a specialized version of the Valid Metadata Manager focusing on type lists.
15
+
16
+ Attributes
17
+ ----------
18
+ view_server : str
19
+ The name of the View Server to use.
20
+ platform_url : str
21
+ URL of the server platform to connect to.
22
+ user_id : str
23
+ The identity of the user calling the method.
24
+ user_pwd : str
25
+ The password associated with the user_id. Defaults to None.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ view_server: str,
31
+ platform_url: str,
32
+ user_id: str,
33
+ user_pwd: Optional[str] = None,
34
+ token: Optional[str] = None,
35
+ ):
36
+ super().__init__(view_server, platform_url, user_id, user_pwd, token)
37
+ self.url_marker = "valid-metadata"
@@ -0,0 +1,28 @@
1
+ """
2
+ View module for pyegeria, containing output formatters and mermaid utilities.
3
+ """
4
+ from pyegeria.view.mermaid_utilities import (
5
+ construct_mermaid_web,
6
+ construct_mermaid_jup,
7
+ load_mermaid,
8
+ render_mermaid,
9
+ save_mermaid_html,
10
+ save_mermaid_graph,
11
+ )
12
+ from pyegeria.view.output_formatter import (
13
+ generate_output,
14
+ resolve_output_formats,
15
+ populate_common_columns,
16
+ )
17
+
18
+ __all__ = [
19
+ "construct_mermaid_web",
20
+ "construct_mermaid_jup",
21
+ "load_mermaid",
22
+ "render_mermaid",
23
+ "save_mermaid_html",
24
+ "save_mermaid_graph",
25
+ "generate_output",
26
+ "resolve_output_formats",
27
+ "populate_common_columns",
28
+ ]
@@ -0,0 +1,514 @@
1
+ """
2
+ SPDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ This module defines Pydantic models for output format sets used in pyegeria.
6
+
7
+ These models provide a structured way to define and validate output formats
8
+ for different types of data, supporting composition and reuse of formats.
9
+
10
+ The module defines the following models:
11
+ - Column: Represents a column in an output format with name, key, and format attributes.
12
+ - Format: Represents a format configuration with types and columns.
13
+ - ActionParameter: Represents a parameter for an action with function, required_params, optional_params, and spec_params.
14
+ - FormatSet: Represents a complete format set with heading, description, aliases, annotations, formats, and actions.
15
+ - FormatSetDict: A dictionary of format sets with methods for backward compatibility.
16
+
17
+ These models are used in the `_output_formats.py` module to replace the dictionary-based
18
+ implementation of output format sets. The models provide several advantages:
19
+ - Type validation: The models ensure that the data has the correct types and structure.
20
+ - Composition: The models support composition of formats, allowing formats to be reused and combined.
21
+ - Documentation: The models provide clear documentation of the data structure.
22
+ - IDE support: The models provide better IDE support, including autocompletion and type hints.
23
+
24
+ Example usage:
25
+ ```python
26
+ from pyegeria._output_format_models import Column, Format, FormatSet
27
+
28
+ # Create columns
29
+ columns = [
30
+ Column(name="Display Name", key="display_name"),
31
+ Column(name="Description", key="description", format=True),
32
+ ]
33
+
34
+ # Create a format
35
+ format = Format(
36
+ types=["TABLE", "DICT"],
37
+ columns=columns,
38
+ )
39
+
40
+ # Create a format set
41
+ format_set = FormatSet(
42
+ heading="Example Format Set",
43
+ description="An example format set",
44
+ formats=[format],
45
+ )
46
+
47
+ # Convert to dictionary for backward compatibility
48
+ format_set_dict = format_set.dict()
49
+ ```
50
+
51
+ The models are designed to be backward compatible with the existing dictionary-based
52
+ implementation. The `FormatSet` class has a `get` method that mimics the behavior of a
53
+ dictionary, and the `FormatSetDict` class provides dictionary-like access to the format sets.
54
+
55
+ Exceptions
56
+ ----------
57
+ The following exceptions may be raised by functions and classes in this module:
58
+ - FileNotFoundError: When attempting to load format sets from a non-existent JSON file.
59
+ - json.JSONDecodeError: When a JSON file cannot be parsed.
60
+ - pydantic.ValidationError: When provided data does not conform to the expected model schema
61
+ for `Column`/`Attribute`, `Format`, `ActionParameter`, `QuestionSpec`, or `FormatSet`.
62
+ - KeyError: Accessing a missing format set label via `FormatSetDict.__getitem__` or
63
+ `FormatSet.get` when a default is not supplied.
64
+ - ValueError: From internal validators if an attribute/format contains invalid values.
65
+ """
66
+
67
+ import json
68
+ import os
69
+ from pathlib import Path
70
+ from typing import Dict, List, Optional, Union, Any
71
+ from pydantic import BaseModel, Field, validator, root_validator
72
+ from loguru import logger
73
+ __all__ = [
74
+ 'Column',
75
+ 'Attribute',
76
+ 'Format',
77
+ 'ActionParameter',
78
+ 'FormatSet',
79
+ 'FormatSetDict',
80
+ 'save_format_sets_to_json',
81
+ 'load_format_sets_from_json',
82
+ ]
83
+
84
+ def save_format_sets_to_json(format_sets: Dict[str, 'FormatSet'], file_path: str) -> None:
85
+ """
86
+ Save format sets to a JSON file.
87
+
88
+ Args:
89
+ format_sets: The format sets to save
90
+ file_path: The path to save the file to
91
+ """
92
+ # Convert FormatSet objects to dictionaries
93
+ serializable_dict = {key: value.dict() for key, value in format_sets.items()}
94
+
95
+ # Create directory if it doesn't exist
96
+ os.makedirs(os.path.dirname(os.path.abspath(file_path)), exist_ok=True)
97
+
98
+ # Write to file
99
+ try:
100
+ with open(file_path, 'w') as f:
101
+ json.dump(serializable_dict, f, indent=2)
102
+ logger.info(f"Format sets saved to {file_path}")
103
+ except Exception as e:
104
+ logger.error(f"Error saving format sets to {file_path}: {e}")
105
+ raise
106
+
107
+ def load_format_sets_from_json(file_path: str) -> Dict[str, 'FormatSet']:
108
+ """
109
+ Load format sets from a JSON file.
110
+
111
+ Args:
112
+ file_path: The path to load the file from
113
+
114
+ Returns:
115
+ Dict[str, FormatSet]: The loaded format sets
116
+ """
117
+ try:
118
+ with open(file_path, 'r') as f:
119
+ data = json.load(f)
120
+
121
+ # Convert dictionaries to FormatSet objects
122
+ format_sets = {}
123
+ for key, value in data.items():
124
+ format_sets[key] = FormatSet(**value)
125
+
126
+ logger.info(f"Format sets loaded from {file_path}")
127
+ return format_sets
128
+ except Exception as e:
129
+ logger.error(f"Error loading format sets from {file_path}: {e}")
130
+ raise
131
+
132
+ class Column(BaseModel):
133
+ """
134
+ Represents an attribute (formerly called a column) in an output format.
135
+
136
+ Fields:
137
+ name: The display name of the attribute
138
+ key: The key used to access the attribute's value in the data
139
+ format: Whether the attribute's value should be formatted
140
+ """
141
+ name: str
142
+ key: str
143
+ format: bool = False
144
+
145
+ # New preferred alias for Column
146
+ Attribute = Column
147
+
148
+ class Format(BaseModel):
149
+ """
150
+ Represents a format configuration with types and attributes.
151
+
152
+ Fields:
153
+ types: The output types this format supports (e.g., "DICT", "TABLE", "ALL")
154
+ attributes: The attributes (formerly columns) to include in the output
155
+ """
156
+ types: List[str]
157
+ attributes: List[Union[Column, Dict[str, Any]]]
158
+
159
+ @root_validator(pre=True)
160
+ def _migrate_columns_to_attributes(cls, values):
161
+ """Support legacy 'columns' by migrating to 'attributes' when loading."""
162
+ if isinstance(values, dict):
163
+ if 'attributes' not in values and 'columns' in values:
164
+ values['attributes'] = values.pop('columns')
165
+ return values
166
+
167
+ @validator('attributes', pre=True)
168
+ def validate_attributes(cls, v):
169
+ """Convert dictionary attributes to Attribute/Column objects."""
170
+ result = []
171
+ for item in v:
172
+ if isinstance(item, dict):
173
+ result.append(Column(**item))
174
+ else:
175
+ result.append(item)
176
+ return result
177
+
178
+ def dict(self, *args, **kwargs):
179
+ """Override dict method to convert Attribute objects back to dictionaries.
180
+ Emits both 'attributes' (preferred) and 'columns' (deprecated) for backward compatibility.
181
+ """
182
+ result = super().dict(*args, **kwargs)
183
+ result['attributes'] = [
184
+ attr if isinstance(attr, dict) else attr.dict()
185
+ for attr in self.attributes
186
+ ]
187
+ # Backward-compat alias
188
+ result['columns'] = list(result['attributes'])
189
+ return result
190
+
191
+ # Backward-compat property to expose 'columns'
192
+ @property
193
+ def columns(self):
194
+ return self.attributes
195
+
196
+ @columns.setter
197
+ def columns(self, value):
198
+ # Allow setting via legacy field
199
+ self.attributes = self.validate_attributes(value)
200
+
201
+ class ActionParameter(BaseModel):
202
+ """
203
+ Represents a parameter for an action.
204
+
205
+ Attributes:
206
+ function: The function to call
207
+ required_params: Parameters that are required from the user
208
+ optional_params: Parameters that are optional from the user
209
+ spec_params: Parameters that are fixed for this action
210
+ """
211
+ function: str
212
+ required_params: List[str] = Field(default_factory=list)
213
+ optional_params: Optional[List[str]] = Field(default_factory=list)
214
+ spec_params: Dict[str, Any] = Field(default_factory=dict)
215
+
216
+ @root_validator(pre=True)
217
+ def _migrate_legacy_user_params(cls, values):
218
+ """Migrate legacy 'user_params' into 'required_params' when loading from older dict/json."""
219
+ if isinstance(values, dict):
220
+ if 'required_params' not in values and 'user_params' in values:
221
+ values['required_params'] = values.pop('user_params')
222
+ return values
223
+
224
+
225
+ class QuestionSpec(BaseModel):
226
+ """
227
+ An example-question specification for a report spec.
228
+
229
+ Attributes:
230
+ perspectives: A list of perspective names for whom these questions are relevant
231
+ questions: Example natural-language questions this report spec can answer
232
+ """
233
+ @root_validator(pre=True)
234
+ def _migrate_legacy_roles(cls, values):
235
+ """Migrate legacy 'roles' field to 'perspectives' when loading from older dict/json."""
236
+ if isinstance(values, dict) and 'perspectives' not in values and 'roles' in values:
237
+ values = dict(values)
238
+ values['perspectives'] = values.pop('roles')
239
+ return values
240
+ perspectives: List[str] = Field(default_factory=list)
241
+ questions: List[str] = Field(default_factory=list)
242
+
243
+ class FormatSet(BaseModel):
244
+ """
245
+ Represents a complete format set with target_type, heading, description, aliases, annotations, formats, and actions.
246
+
247
+ Attributes:
248
+ target_type: The related Open Metadata entity type this format set targets (e.g., Glossary, Term). Optional.
249
+ heading: A title for the format set
250
+ description: A description of what the format set is for
251
+ aliases: Alternative names that can be used to reference this format set
252
+ annotations: Additional metadata, like wiki links
253
+ family: Optional tag to group related format sets for organization/searching
254
+ formats: A list of format configurations
255
+ action: Optional action associated with the format set
256
+ get_additional_props: Optional action used to retrieve additional properties for a format set
257
+ """
258
+ target_type: Optional[str] = None
259
+ heading: str
260
+ description: str
261
+ aliases: List[str] = Field(default_factory=list)
262
+ annotations: Dict[str, List[str]] = Field(default_factory=dict)
263
+ family: Optional[str] = None
264
+ formats: List[Union[Format, Dict[str, Any]]]
265
+ action: Optional[Union[ActionParameter, Dict[str, Any]]] = None
266
+ get_additional_props: Optional[Union[ActionParameter, Dict[str, Any]]] = None
267
+ # Optional: example questions and perspectives this report spec can address
268
+ question_spec: Optional[List[Union[QuestionSpec, Dict[str, Any]]]] = None
269
+
270
+ @root_validator(pre=True)
271
+ def _migrate_legacy_fields(cls, values):
272
+ """Migrate legacy fields from older saved JSON (entity_type -> target_type)."""
273
+ if isinstance(values, dict):
274
+ if 'entity_type' in values and 'target_type' not in values:
275
+ values['target_type'] = values.pop('entity_type')
276
+ return values
277
+
278
+ @validator('formats', pre=True)
279
+ def validate_formats(cls, v):
280
+ """Convert dictionary formats to Format objects."""
281
+ result = []
282
+ for item in v:
283
+ if isinstance(item, dict):
284
+ result.append(Format(**item))
285
+ else:
286
+ result.append(item)
287
+ return result
288
+
289
+ @validator('question_spec', pre=True)
290
+ def validate_question_spec(cls, v):
291
+ """Convert dictionary items to QuestionSpec objects when provided."""
292
+ if v is None:
293
+ return None
294
+ out: List[QuestionSpec] = []
295
+ for item in v:
296
+ if isinstance(item, dict):
297
+ out.append(QuestionSpec(**item))
298
+ else:
299
+ out.append(item)
300
+ return out
301
+
302
+ @validator('action', 'get_additional_props', pre=True)
303
+ def validate_action_like(cls, v):
304
+ """Convert dictionary action-like fields to ActionParameter objects. Accepts legacy list shape."""
305
+ if v is None:
306
+ return None
307
+ # Backward compatibility: if a list is provided, use the first element
308
+ if isinstance(v, list):
309
+ if not v:
310
+ return None
311
+ logger.warning("FormatSet.action/get_additional_props provided as a list; coercing first element to dict. This shape is deprecated.")
312
+ v = v[0]
313
+ if isinstance(v, dict):
314
+ return ActionParameter(**v)
315
+ return v
316
+
317
+ def dict(self, *args, **kwargs):
318
+ """Override dict method to convert nested objects back to dictionaries."""
319
+ result = super().dict(*args, **kwargs)
320
+ result['formats'] = [
321
+ format if isinstance(format, dict) else format.dict()
322
+ for format in self.formats
323
+ ]
324
+ if self.action is not None:
325
+ result['action'] = self.action if isinstance(self.action, dict) else self.action.dict()
326
+ if self.get_additional_props is not None:
327
+ result['get_additional_props'] = (
328
+ self.get_additional_props if isinstance(self.get_additional_props, dict) else self.get_additional_props.dict()
329
+ )
330
+ if self.question_spec is not None:
331
+ result['question_spec'] = [
332
+ item if isinstance(item, dict) else item.dict() for item in self.question_spec
333
+ ]
334
+ return result
335
+
336
+ def get(self, key, default=None):
337
+ """
338
+ Dictionary-like get method for backward compatibility.
339
+
340
+ Args:
341
+ key: The key to look up
342
+ default: The default value to return if the key is not found
343
+
344
+ Returns:
345
+ The value for the key if found, otherwise the default value
346
+ """
347
+ if hasattr(self, key):
348
+ return getattr(self, key)
349
+ return default
350
+
351
+ class FormatSetDict(Dict[str, FormatSet]):
352
+ """
353
+ A dictionary of format sets, with methods for backward compatibility.
354
+
355
+ This class allows the format sets to be accessed like a dictionary,
356
+ while providing the validation and structure of Pydantic models.
357
+
358
+ It also provides the ability to find format sets by either name or alias,
359
+ making it easier to work with format sets without knowing their exact name.
360
+ """
361
+ def __init__(self, *args, **kwargs):
362
+ super().__init__(*args, **kwargs)
363
+
364
+ def find_by_name_or_alias(self, key, default=None):
365
+ """
366
+ Find a format set by either name or alias.
367
+
368
+ This method first checks if the key exists directly in the dictionary.
369
+ If not found, it searches through all format sets to find one with a matching alias.
370
+
371
+ Args:
372
+ key: The name or alias to look up
373
+ default: The default value to return if the key is not found
374
+
375
+ Returns:
376
+ FormatSet: The format set if found, otherwise the default value
377
+ """
378
+ # First try to find by name (key)
379
+ format_set = super().get(key, None)
380
+
381
+ # If not found by name, try to find by alias
382
+ if format_set is None:
383
+ for value in self.values():
384
+ if key in value.aliases:
385
+ format_set = value
386
+ break
387
+
388
+ # Return the format set if found, otherwise the default value
389
+ return format_set if format_set is not None else default
390
+
391
+ def get(self, key, default=None):
392
+ """
393
+ Get a format set by name or alias.
394
+
395
+ This method first checks if the key exists directly in the dictionary.
396
+ If not found, it searches through all format sets to find one with a matching alias.
397
+
398
+ Args:
399
+ key: The name or alias to look up
400
+ default: The default value to return if the key is not found
401
+
402
+ Returns:
403
+ FormatSet: The format set if found, otherwise the default value
404
+ """
405
+ return self.find_by_name_or_alias(key, default)
406
+
407
+ def filter_by_family(self, family: str) -> Dict[str, FormatSet]:
408
+ """
409
+ Return a plain dict of format sets whose `family` matches the given value.
410
+
411
+ Matching rules
412
+ - Case-insensitive comparison
413
+ - Leading/trailing whitespace in the input and stored family are ignored
414
+ - Pass an empty string ("") to match entries with no family assigned
415
+
416
+ Args:
417
+ family: Family name to match (case-insensitive). Use "" to select entries with no family.
418
+
419
+ Returns:
420
+ dict[str, FormatSet]: Mapping of spec name -> FormatSet for matching entries.
421
+ """
422
+ # Normalize the requested family
423
+ fam_norm = (family or "").strip().lower()
424
+ result: Dict[str, FormatSet] = {}
425
+ for name, fs in self.items():
426
+ fs_family_raw = getattr(fs, "family", None)
427
+ fs_family_norm = (fs_family_raw or "").strip().lower()
428
+ if fam_norm == "":
429
+ # Select items with no family set
430
+ if fs_family_norm == "":
431
+ result[name] = fs
432
+ else:
433
+ if fs_family_norm == fam_norm:
434
+ result[name] = fs
435
+ return result
436
+
437
+ def values(self):
438
+ """Get all format sets."""
439
+ return super().values()
440
+
441
+ def keys(self):
442
+ """Get all format set names."""
443
+ return super().keys()
444
+
445
+ def items(self):
446
+ """Get all format set items."""
447
+ return super().items()
448
+
449
+ def __getitem__(self, key):
450
+ """
451
+ Get a format set by name or alias.
452
+
453
+ This method first checks if the key exists directly in the dictionary.
454
+ If not found, it searches through all format sets to find one with a matching alias.
455
+ If still not found, it raises a KeyError.
456
+
457
+ Args:
458
+ key: The name or alias to look up
459
+
460
+ Returns:
461
+ FormatSet: The format set if found
462
+
463
+ Raises:
464
+ KeyError: If the format set is not found by name or alias
465
+ """
466
+ format_set = self.find_by_name_or_alias(key, None)
467
+ if format_set is None:
468
+ raise KeyError(key)
469
+ return format_set
470
+
471
+ def __setitem__(self, key, value):
472
+ """Set a format set by name."""
473
+ if isinstance(value, dict):
474
+ value = FormatSet(**value)
475
+ super().__setitem__(key, value)
476
+
477
+ def __contains__(self, key):
478
+ """
479
+ Check if a format set exists by name or alias.
480
+
481
+ Args:
482
+ key: The name or alias to check
483
+
484
+ Returns:
485
+ bool: True if the format set exists, False otherwise
486
+ """
487
+ return self.find_by_name_or_alias(key, None) is not None
488
+
489
+ def to_dict(self):
490
+ """Convert all format sets to dictionaries."""
491
+ return {key: value.dict() for key, value in self.items()}
492
+
493
+ def save_to_json(self, file_path: str) -> None:
494
+ """
495
+ Save format sets to a JSON file.
496
+
497
+ Args:
498
+ file_path: The path to save the file to
499
+ """
500
+ save_format_sets_to_json(self, file_path)
501
+
502
+ @classmethod
503
+ def load_from_json(cls, file_path: str) -> 'FormatSetDict':
504
+ """
505
+ Load format sets from a JSON file.
506
+
507
+ Args:
508
+ file_path: The path to load the file from
509
+
510
+ Returns:
511
+ FormatSetDict: A new FormatSetDict instance with the loaded format sets
512
+ """
513
+ format_sets = load_format_sets_from_json(file_path)
514
+ return cls(format_sets)
@@ -0,0 +1,14 @@
1
+ """
2
+ Deprecated module shim.
3
+ This module has been renamed to pyegeria.base_report_formats.
4
+ It re-exports all public APIs and raises DeprecationWarning on import.
5
+ """
6
+ import warnings
7
+
8
+ warnings.warn(
9
+ "pyegeria._output_formats is deprecated; use pyegeria.base_report_formats instead",
10
+ DeprecationWarning,
11
+ stacklevel=2,
12
+ )
13
+
14
+ from pyegeria.view.base_report_formats import * # noqa: F401,F403