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,1752 @@
1
+ """
2
+ PDX-License-Identifier: Apache-2.0
3
+ Copyright Contributors to the ODPi Egeria project.
4
+
5
+ Manage external references to a variety of artifacts.
6
+
7
+ """
8
+
9
+ import asyncio
10
+ from typing import Optional
11
+
12
+ from loguru import logger
13
+ from pydantic import HttpUrl
14
+
15
+ from pyegeria.core._globals import NO_GUID_RETURNED
16
+ from pyegeria.view.base_report_formats import select_report_spec, get_report_spec_match
17
+ from pyegeria.core.config import settings
18
+ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
19
+ TemplateRequestBody,
20
+ UpdateElementRequestBody, NewRelationshipRequestBody,
21
+ DeleteElementRequestBody, DeleteRelationshipRequestBody)
22
+ from pyegeria.view.output_formatter import (generate_output,
23
+ _extract_referenceable_properties, populate_columns_from_properties,
24
+ get_required_relationships)
25
+ from pyegeria.core.utils import dynamic_catch
26
+
27
+ app_settings = settings
28
+ EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
29
+ EXTERNAL_REFERENCE_PROPS = ["ExternalReferenceProperties", "ExternalDataSourceProperties",
30
+ "ExternalModelSourceProperties",
31
+ "RelatedMediaProperties", "CitedDocumentProperties"]
32
+
33
+ EXTERNAL_REFERENCE_TYPES = ["ExternalReference", "ExternalDataSource", "ExternalModelSource",
34
+ "RelatedMedia", "CitedDocument"]
35
+ from pyegeria.core._server_client import ServerClient
36
+
37
+
38
+ class ExternalReferences(ServerClient):
39
+ """
40
+ Establish linkage to external references which can be a variety of artifacts. Including media,
41
+ documents, data, and more. Keep in mind that there are several sub-types of external references, each
42
+ with their own property body. This includes:
43
+
44
+ * ExternalReferenceProperties
45
+ * ExternalDataSourceProperties
46
+ * ExternalModelSourceProperties
47
+ * RelatedMediaProperties
48
+ * CitedDocumentProperties
49
+
50
+ Review the documentation on the website for more details.
51
+
52
+ Attributes:
53
+
54
+ server_name: str
55
+ The name of the View Server to connect to.
56
+ platform_url : str
57
+ URL of the server platform to connect to
58
+ user_id : str
59
+ The identity of the user calling the method - this sets a default optionally used by the methods
60
+ when the user doesn't pass the user_id on a method call.
61
+ user_pwd: str
62
+ The password associated with the user_id. Defaults to None
63
+ token: str
64
+ An optional bearer token
65
+
66
+ """
67
+
68
+ def __init__(self, view_server: str, platform_url: str, user_id: str, user_pwd: Optional[str] = None, token: Optional[str] = None, ):
69
+ self.view_server = view_server
70
+ self.platform_url = platform_url
71
+ self.user_id = user_id
72
+ self.user_pwd = user_pwd
73
+
74
+ ServerClient.__init__(self, view_server, platform_url, user_id, user_pwd, token)
75
+ # result = self.get_platform_origin()
76
+ # logger.info(f"ExternalReferences initialized, platform origin is: {result}")
77
+ self.command_root: str = (
78
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external-links")
79
+
80
+ @dynamic_catch
81
+ async def _async_create_external_reference(self, body: Optional[dict | NewElementRequestBody] = None) -> str:
82
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
83
+ and classification will be used to create a simple, self-anchored external_reference.
84
+ Collections: https://egeria-project.org/concepts/external_reference
85
+ Async version.
86
+
87
+ Parameters
88
+ ----------
89
+
90
+
91
+ body: dict | NewElementRequestBody, optional
92
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
93
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
94
+ validated before being used.
95
+
96
+ Returns
97
+ -------
98
+ str - the guid of the created external_reference
99
+
100
+ Raises
101
+ ------
102
+ PyegeriaException
103
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
104
+ Egeria errors.
105
+ ValidationError
106
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
107
+ NotAuthorizedException
108
+ The principle specified by the user_id does not have authorization for the requested action
109
+
110
+ Notes:
111
+ -----
112
+ simple:
113
+ {
114
+ "class": "NewElementRequestBody",
115
+ "isOwnAnchor": true,
116
+ "properties": {
117
+ "class": "ExternalReferenceProperties",
118
+ "qualifiedName": "Must provide a unique name here",
119
+ "name": "Add display name here",
120
+ "description": "Add description of the external_reference here",
121
+ "category": "Add appropriate valid value for type",
122
+ "referenceTitle: "Add reference title here",
123
+ "referenceAbstract": "Add reference abstract here",
124
+ "authors": ["Add author names here"],
125
+ "url": "Add url here",
126
+ "datePublished": "2023-01-01",
127
+ "dateConnected": "2023-01-01",
128
+ "dateCreated": "2023-01-01",
129
+ }
130
+ }
131
+
132
+ For related media use this properties body:
133
+ {
134
+ "class": "NewElementRequestBody",
135
+ "isOwnAnchor": true,
136
+ "properties": {
137
+ "class": "RelatedMediaProperties",
138
+ "qualifiedName": "Must provide a unique name here",
139
+ "name": "Add display name here",
140
+ "description": "Add description of the external_reference here",
141
+ "category": "Add appropriate valid value for type",
142
+ "referenceTitle: "Add reference title here",
143
+ "referenceAbstract": "Add reference abstract here",
144
+ "authors": ["Add author names here"],
145
+ "url": "Add url here",
146
+ "datePublished": "2023-01-01",
147
+ "dateConnected": "2023-01-01",
148
+ "dateCreated": "2023-01-01",
149
+ "mediaType": "Add media type here",
150
+ "mediaTypeOtherId": "Add media type other id here",
151
+ "defaultMediaUsage": "Add default media usage here",
152
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
153
+ }
154
+ }
155
+
156
+ See https://egeria-project.org/types/0/0015-Linked-Media-Types/ for more information on media types and
157
+ valid values.
158
+
159
+ """
160
+
161
+ url = f"{self.command_root}/external-references"
162
+ return await self._async_create_element_body_request(url, EXTERNAL_REFERENCE_PROPS, body)
163
+
164
+ @dynamic_catch
165
+ def create_external_reference(self, body: Optional[dict | NewElementRequestBody] = None) -> str:
166
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
167
+ and classification will be used to create a simple, self-anchored external_reference.
168
+ Collections: https://egeria-project.org/concepts/external_reference
169
+ Async version.
170
+
171
+ Parameters
172
+ ----------
173
+
174
+
175
+ body: dict | NewElementRequestBody, optional
176
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
177
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
178
+ validated before being used.
179
+
180
+ Returns
181
+ -------
182
+ str - the guid of the created external_reference
183
+
184
+ Raises
185
+ ------
186
+ PyegeriaException
187
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
188
+ Egeria errors.
189
+ ValidationError
190
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
191
+ NotAuthorizedException
192
+ The principle specified by the user_id does not have authorization for the requested action
193
+
194
+ Notes:
195
+ -----
196
+ simple:
197
+ {
198
+ "class": "NewElementRequestBody",
199
+ "isOwnAnchor": true,
200
+ "properties": {
201
+ "class": "ExternalReferenceProperties",
202
+ "qualifiedName": "Must provide a unique name here",
203
+ "name": "Add display name here",
204
+ "description": "Add description of the external_reference here",
205
+ "category": "Add appropriate valid value for type",
206
+ "referenceTitle": "Add reference title here",
207
+ "referenceAbstract": "Add reference abstract here",
208
+ "authors": ["Add author names here"],
209
+ "url": "Add url here",
210
+ "sources": "Add sources here",
211
+ "license": "Add license here",
212
+ "copyright": "Add copyright here",
213
+ "attribution": "Add attribution here"
214
+ }
215
+ }
216
+
217
+ For related media use this properties body:
218
+ {
219
+ "class": "NewElementRequestBody",
220
+ "isOwnAnchor": true,
221
+ "properties": {
222
+ "class": "RelatedMediaProperties",
223
+ "qualifiedName": "Must provide a unique name here",
224
+ "name": "Add display name here",
225
+ "description": "Add description of the external_reference here",
226
+ "category": "Add appropriate valid value for type",
227
+ "referenceTitle": "Add reference title here",
228
+ "referenceAbstract": "Add reference abstract here",
229
+ "authors": ["Add author names here"],
230
+ "url": "Add url here",
231
+ "sources": "Add sources here",
232
+ "license": "Add license here",
233
+ "copyright": "Add copyright here",
234
+ "attribution": "Add attribution here",
235
+ "datePublished": "2023-01-01",
236
+ "dateConnected": "2023-01-01",
237
+ "dateCreated": "2023-01-01",
238
+ "mediaType": "Add media type here",
239
+ "mediaTypeOtherId": "Add media type other id here",
240
+ "defaultMediaUsage": "Add default media usage here",
241
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
242
+ }
243
+ }
244
+
245
+ For CitedDocument use this properties body:
246
+ {
247
+ "class": "NewElementRequestBody",
248
+ "isOwnAnchor": true,
249
+ "properties": {
250
+ "class": "CitedDocumentProperties",
251
+ "qualifiedName": "Must provide a unique name here",
252
+ "name": "Add display name here",
253
+ "description": "Add description of the external_reference here",
254
+ "category": "Add appropriate valid value for type",
255
+ "numberOfPates": int,
256
+ "pageRange": "Add page range here",
257
+ "publicationSeries": "Add publication series here",
258
+ "publicationSeriesVolume": "Add publication series volume here",
259
+ "publisher": "Add publisher here",
260
+ "edition": "Add edition here",
261
+ "firstPublicationDate": "2023-01-01",
262
+ "publicationDate": "2023-01-01",
263
+ "publicationCity": "Add publication city here",
264
+ "publicationYear": "publication year",
265
+ "publicationNumbers": ["string"],
266
+ "defaultMediaUsage": "Add default media usage here",
267
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
268
+ "referenceTitle": "Add reference title here",
269
+ "referenceAbstract": "Add reference abstract here",
270
+ "authors": ["Add author names here"],
271
+ "url": "Add url here",
272
+ "sources": "Add sources here",
273
+ "license": "Add license here",
274
+ "copyright": "Add copyright here",
275
+ "attribution": "Add attribution here"
276
+ }
277
+ }
278
+
279
+ See https://egeria-project.org/types/0/0015-Linked-Media-Types/ for more information on media types and
280
+ valid values.
281
+
282
+
283
+ """
284
+
285
+ return asyncio.get_event_loop().run_until_complete(self._async_create_external_reference(body))
286
+
287
+ #######
288
+
289
+ @dynamic_catch
290
+ async def _async_create_external_reference_from_template(self, body: Optional[dict | TemplateRequestBody] = None) -> str:
291
+ """Create a new metadata element to represent a external_reference using an existing metadata element as a template.
292
+ The template defines additional classifications and relationships that are added to the new external_reference.
293
+ Async version.
294
+
295
+ Parameters
296
+ ----------
297
+
298
+ body: dict
299
+ A dict representing the details of the external_reference to create.
300
+
301
+ Returns
302
+ -------
303
+ str - the guid of the created external_reference
304
+
305
+ Raises
306
+ ------
307
+ PyegeriaInvalidParameterException
308
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
309
+ PyegeriaAPIException
310
+ Raised by the server when an issue arises in processing a valid request
311
+ NotAuthorizedException
312
+ The principle specified by the user_id does not have authorization for the requested action
313
+
314
+ Notes
315
+ -----
316
+ JSON Structure looks like:
317
+
318
+ {
319
+ "class": "TemplateRequestBody",
320
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
321
+ "isOwnAnchor": false,
322
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
323
+ "parentRelationshipTypeName": "open metadata type name",
324
+ "parentAtEnd1": true,
325
+ "templateGUID": "template GUID",
326
+ "replacementProperties": {
327
+ "class": "ElementProperties",
328
+ "propertyValueMap" : {
329
+ "propertyName" : {
330
+ "class": "PrimitiveTypePropertyValue",
331
+ "typeName": "string",
332
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
333
+ "primitiveValue" : "value of property"
334
+ }
335
+ }
336
+ },
337
+ "placeholderPropertyValues" : {
338
+ "placeholderProperty1Name" : "property1Value",
339
+ "placeholderProperty2Name" : "property2Value"
340
+ }
341
+ }
342
+
343
+ """
344
+
345
+ if isinstance(body, TemplateRequestBody):
346
+ validated_body = body
347
+
348
+ elif isinstance(body, dict):
349
+ validated_body = self._template_request_adapter.validate_python(body)
350
+
351
+ url = f"{self.command_root}/external-references/from-template"
352
+ json_body = validated_body.model_dump_json(indent=2, exclude_none=True)
353
+ logger.info(json_body)
354
+ resp = await self._async_make_request("POST", url, json_body, is_json=True)
355
+ logger.info(f"Create external_reference from template with GUID: {resp.json().get('guid')}")
356
+ return resp.json().get("guid", NO_GUID_RETURNED)
357
+
358
+ @dynamic_catch
359
+ def create_external_reference_from_template(self, body: Optional[dict | TemplateRequestBody] = None) -> str:
360
+ """Create a new metadata element to represent a external_reference using an existing metadata element as a template.
361
+ The template defines additional classifications and relationships that are added to the new external_reference.
362
+
363
+ Parameters
364
+ ----------
365
+ body: dict
366
+ A dict representing the details of the external_reference to create.
367
+
368
+ Returns
369
+ -------
370
+ str - the guid of the created external_reference
371
+
372
+ Raises
373
+ ------
374
+ PyegeriaInvalidParameterException
375
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
376
+ PyegeriaAPIException
377
+ Raised by the server when an issue arises in processing a valid request
378
+ NotAuthorizedException
379
+ The principle specified by the user_id does not have authorization for the requested action
380
+
381
+ Notes
382
+ -----
383
+ JSON Structure looks like:
384
+
385
+ {
386
+ "class": "TemplateRequestBody",
387
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
388
+ "isOwnAnchor": false,
389
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
390
+ "parentRelationshipTypeName": "open metadata type name",
391
+ "parentAtEnd1": true,
392
+ "templateGUID": "template GUID",
393
+ "replacementProperties": {
394
+ "class": "ElementProperties",
395
+ "propertyValueMap" : {
396
+ "propertyName" : {
397
+ "class": "PrimitiveTypePropertyValue",
398
+ "typeName": "string",
399
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
400
+ "primitiveValue" : "value of property"
401
+ }
402
+ }
403
+ },
404
+ "placeholderPropertyValues" : {
405
+ "placeholderProperty1Name" : "property1Value",
406
+ "placeholderProperty2Name" : "property2Value"
407
+ }
408
+ }
409
+ """
410
+ loop = asyncio.get_event_loop()
411
+ resp = loop.run_until_complete(self._async_create_external_reference_from_template(body))
412
+ return resp
413
+
414
+ #
415
+ # Manage external_references
416
+ #
417
+
418
+ @dynamic_catch
419
+ async def _async_update_external_reference(self, external_reference_guid: str,
420
+ body: dict | UpdateElementRequestBody) -> None:
421
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
422
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
423
+ Collections: https://egeria-project.org/concepts/external_reference
424
+
425
+ Async version.
426
+ Parameters
427
+ ----------
428
+ external_reference_guid: str
429
+ The guid of the external_reference to update.
430
+
431
+ body: dict | UpdateElementRequestBody, optional
432
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
433
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
434
+ validated before being used.
435
+ merge_update: bool, optional, default = True
436
+ If true then property changes will be overlaid on top of existing properties. If false, existing
437
+ properties will all be replaced by the set provided in the update request.
438
+
439
+ Returns
440
+ -------
441
+ None
442
+
443
+ Raises
444
+ ------
445
+ PyegeriaException
446
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
447
+ Egeria errors.
448
+ ValidationError
449
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
450
+ NotAuthorizedException
451
+ The principle specified by the user_id does not have authorization for the requested action
452
+
453
+ Notes:
454
+ -----
455
+ simple example:
456
+ {
457
+ "class" : "UpdateElementRequestBody",
458
+ "properties": {
459
+ "class" : "CollectionProperties",
460
+ "qualifiedName": "Must provide a unique name here",
461
+ "name" : "Add display name here",
462
+ "description" : "Add description of the external_reference here",
463
+ "category": "Add appropriate valid value for type"
464
+ },
465
+ "externalSourceGUID": "add guid here",
466
+ "externalSourceName": "add qualified name here",
467
+ "effectiveTime" : "{{$isoTimestamp}}",
468
+ "forLineage" : false,
469
+ "forDuplicateProcessing" : false
470
+ }
471
+ """
472
+
473
+ # try:
474
+
475
+ url = (f"{self.command_root}/external-references/{external_reference_guid}/update")
476
+ await self._async_update_element_body_request(url, EXTERNAL_REFERENCE_PROPS, body)
477
+
478
+ @dynamic_catch
479
+ def update_external_reference(self, external_reference_guid: str, body: dict | NewElementRequestBody) -> None:
480
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
481
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
482
+ Collections: https://egeria-project.org/concepts/external_reference
483
+
484
+ Parameters
485
+ ----------
486
+ external_reference_guid: str
487
+ The guid of the external_reference to update.
488
+
489
+ body: dict | NewElementRequestBody, optional
490
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
491
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
492
+ validated before being used.
493
+ merge_update: bool, optional, default = True
494
+ If true then property changes will be overlaid on top of existing properties. If false, existing
495
+ properties will all be replaced by the set provided in the update request.
496
+
497
+ Returns
498
+ -------
499
+ None
500
+
501
+ Raises
502
+ ------
503
+ PyegeriaException
504
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
505
+ Egeria errors.
506
+ ValidationError
507
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
508
+ NotAuthorizedException
509
+ The principle specified by the user_id does not have authorization for the requested action
510
+
511
+ Notes:
512
+ -----
513
+ simple example:
514
+ {
515
+ "class" : "UpdateElementRequestBody",
516
+ "properties": {
517
+ "class" : "CollectionProperties",
518
+ "qualifiedName": "Must provide a unique name here",
519
+ "name" : "Add display name here",
520
+ "description" : "Add description of the external_reference here",
521
+ "category": "Add appropriate valid value for type"
522
+ },
523
+ "externalSourceGUID": "add guid here",
524
+ "externalSourceName": "add qualified name here",
525
+ "effectiveTime" : "{{$isoTimestamp}}",
526
+ "forLineage" : false,
527
+ "forDuplicateProcessing" : false
528
+ }
529
+ """
530
+
531
+ return asyncio.get_event_loop().run_until_complete(
532
+ self._async_update_external_reference(external_reference_guid, body))
533
+
534
+ @dynamic_catch
535
+ async def _async_link_external_reference(self, element_guid: str, ext_ref_guid: str,
536
+ body: Optional[dict | NewRelationshipRequestBody] = None) -> None:
537
+ """ Attach an element to an external reference.
538
+ Async version.
539
+
540
+ Parameters
541
+ ----------
542
+ element_guid: str
543
+ The unique identifier of the element.
544
+ ext_ref_guid: str
545
+ The identifier of the external reference.
546
+ body: dict | NewRelationshipRequestBody, optional, default = None
547
+ A structure representing the details of the relationship.
548
+
549
+ Returns
550
+ -------
551
+ Nothing
552
+
553
+ Raises
554
+ ------
555
+ PyegeriaInvalidParameterException
556
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
557
+ PyegeriaAPIException
558
+ Raised by the server when an issue arises in processing a valid request
559
+ NotAuthorizedException
560
+ The principle specified by the user_id does not have authorization for the requested action
561
+
562
+ Notes
563
+ -----
564
+ JSON Structure looks like:
565
+ {
566
+ "class" : "NewRelationshipRequestBody",
567
+ "externalSourceGUID": "add guid here",
568
+ "externalSourceName": "add qualified name here",
569
+ "effectiveTime" : "{{$isoTimestamp}}",
570
+ "forLineage" : false,
571
+ "forDuplicateProcessing" : false,
572
+ "properties": {
573
+ "class": "ExternalReferenceLinkProperties",",
574
+ "label": "add label here",
575
+ "description": "add description here",
576
+ "effectiveFrom": "{{$isoTimestamp}}",
577
+ "effectiveTo": "{{$isoTimestamp}}"
578
+ }
579
+ }
580
+
581
+ """
582
+
583
+ url = url = (f"{self.command_root}/elements/{element_guid}/external-references/{ext_ref_guid}/attach")
584
+ await self._async_new_relationship_request(url, "ExternalReferenceLinkProperties", body)
585
+ logger.info(f"Linking element {element_guid} to ext. ref. {ext_ref_guid}")
586
+
587
+ @dynamic_catch
588
+ def link_external_reference(self, element_guid: str, ext_ref_guid: str,
589
+ body: Optional[dict | NewRelationshipRequestBody] = None):
590
+ """ Attach an element to an external reference.
591
+
592
+ Parameters
593
+ ----------
594
+ element_guid: str
595
+ The unique identifier of the element.
596
+ ext_ref_guid: str
597
+ The identifier of the external reference.
598
+ body: dict | NewRelationshipRequestBody, optional, default = None
599
+ A structure representing the details of the relationship.
600
+
601
+ Returns
602
+ -------
603
+ Nothing
604
+
605
+ Raises
606
+ ------
607
+ PyegeriaInvalidParameterException
608
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
609
+ PyegeriaAPIException
610
+ Raised by the server when an issue arises in processing a valid request
611
+ NotAuthorizedException
612
+ The principle specified by the user_id does not have authorization for the requested action
613
+
614
+ Notes
615
+ -----
616
+ JSON Structure looks like:
617
+ {
618
+ "class" : "NewRelationshipRequestBody",
619
+ "externalSourceGUID": "add guid here",
620
+ "externalSourceName": "add qualified name here",
621
+ "effectiveTime" : "{{$isoTimestamp}}",
622
+ "forLineage" : false,
623
+ "forDuplicateProcessing" : false,
624
+ "properties": {
625
+ "class": "ExternalReferenceLinkProperties",",
626
+ "label": "add label here",
627
+ "description": "add description here",
628
+ "effectiveFrom": "{{$isoTimestamp}}",
629
+ "effectiveTo": "{{$isoTimestamp}}"
630
+ }
631
+ }
632
+ """
633
+ loop = asyncio.get_event_loop()
634
+ loop.run_until_complete(self._async_link_external_reference(element_guid, ext_ref_guid, body))
635
+
636
+ @dynamic_catch
637
+ async def _async_detach_external_reference(self, element_guid: str, ext_ref_guid: str,
638
+ body: Optional[dict | DeleteRelationshipRequestBody] = None) -> None:
639
+ """ Detach an element from an external reference; body is optional. Async version.
640
+
641
+ Parameters
642
+ ----------
643
+ element_guid: str
644
+ The unique identifier of the subscriber.
645
+ ext_ref_guid: str
646
+ The unique identifier of the subscription.
647
+ body: dict | DeleteRelationshipRequestBody, optional, default = None
648
+ A structure representing the details of the relationship.
649
+
650
+ Returns
651
+ -------
652
+ Nothing
653
+
654
+ Raises
655
+ ------
656
+ PyegeriaInvalidParameterException
657
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
658
+ PyegeriaAPIException
659
+ Raised by the server when an issue arises in processing a valid request
660
+ NotAuthorizedException
661
+ The principle specified by the user_id does not have authorization for the requested action
662
+
663
+ Notes
664
+ -----
665
+ JSON Structure looks like:
666
+ {
667
+ "class": "DeleteRelationshipRequestBody",
668
+ "externalSourceGUID": "add guid here",
669
+ "externalSourceName": "add qualified name here",
670
+ "effectiveTime": "{{$isoTimestamp}}",
671
+ "forLineage": false,
672
+ "forDuplicateProcessing": false
673
+ }
674
+ """
675
+ url = (f"{self.command_root}/elements/{element_guid}/external_references/{ext_ref_guid}/detach")
676
+
677
+ await self._async_delete_element_request(url, body)
678
+ logger.info(f"Detached element {element_guid} from external reference {ext_ref_guid}")
679
+
680
+ def detach_external_reference(self, element_guid: str, ext_ref_guid: str, body: Optional[dict | DeleteRelationshipRequestBody] = None):
681
+ """ Detach an element from an external reference. Request body is optional.
682
+
683
+ Parameters
684
+ ----------
685
+ element_guid: str
686
+ The unique identifier of the subscriber.
687
+ ext_ref_guid: str
688
+ The unique identifier of the subscription.
689
+ body: dict, optional, default = None
690
+ A dict representing the details of the relationship.
691
+
692
+ Returns
693
+ -------
694
+ Nothing
695
+
696
+ Raises
697
+ ------
698
+ PyegeriaInvalidParameterException
699
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
700
+ PyegeriaAPIException
701
+ Raised by the server when an issue arises in processing a valid request
702
+ NotAuthorizedException
703
+ The principle specified by the user_id does not have authorization for the requested action
704
+
705
+ Notes
706
+ -----
707
+ JSON Structure looks like:
708
+ {
709
+ "class": "DeleteRelationshipRequestBody",
710
+ "externalSourceGUID": "add guid here",
711
+ "externalSourceName": "add qualified name here",
712
+ "effectiveTime": "{{$isoTimestamp}}",
713
+ "forLineage": false,
714
+ "forDuplicateProcessing": false
715
+ }
716
+ """
717
+ loop = asyncio.get_event_loop()
718
+ loop.run_until_complete(self._async_detach_external_reference(element_guid, ext_ref_guid, body))
719
+
720
+ @dynamic_catch
721
+ async def _async_link_media_reference(self, element_guid: str, media_ref_guid: str,
722
+ body: Optional[dict | NewRelationshipRequestBody] = None) -> None:
723
+ """ Attach an element to a related media reference.
724
+ Async version.
725
+
726
+ Parameters
727
+ ----------
728
+ element_guid: str
729
+ The unique identifier of the element.
730
+ media_ref_guid: str
731
+ The identifier of the external media reference.
732
+ body: dict | NewRelationshipRequestBody, optional, default = None
733
+ A structure representing the details of the relationship.
734
+
735
+ Returns
736
+ -------
737
+ Nothing
738
+
739
+ Raises
740
+ ------
741
+ PyegeriaInvalidParameterException
742
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
743
+ PyegeriaAPIException
744
+ Raised by the server when an issue arises in processing a valid request
745
+ NotAuthorizedException
746
+ The principle specified by the user_id does not have authorization for the requested action
747
+
748
+ Notes
749
+ -----
750
+ JSON Structure looks like:
751
+ {
752
+ "class" : "NewRelationshipRequestBody",
753
+ "externalSourceGUID": "add guid here",
754
+ "externalSourceName": "add qualified name here",
755
+ "effectiveTime" : "{{$isoTimestamp}}",
756
+ "forLineage" : false,
757
+ "forDuplicateProcessing" : false,
758
+ "properties": {
759
+ "class": "MediaReferenceProperties",
760
+ "mediaId": "",
761
+ "description": "",
762
+ "mediaUsage": "ICON",
763
+ "mediaUsageOtherId": "",
764
+ "effectiveFrom": "{{$isoTimestamp}}",
765
+ "effectiveTo": "{{$isoTimestamp}}"
766
+ }
767
+ }
768
+
769
+ """
770
+ url = f"{self.command_root}/elements/{element_guid}/media-references/{media_ref_guid}/attach"
771
+ await self._async_new_relationship_request(url, "MediaReferenceProperties", body)
772
+ logger.info(f"Linking element {element_guid} to media reference {media_ref_guid}")
773
+
774
+ @dynamic_catch
775
+ def link_media_reference(self, element_guid: str, media_ref_guid: str,
776
+ body: Optional[dict | NewRelationshipRequestBody] = None):
777
+ """ Attach an element to an external media reference.
778
+
779
+ Parameters
780
+ ----------
781
+ element_guid: str
782
+ The unique identifier of the element.
783
+ media_ref_guid: str
784
+ The identifier of the external reference.
785
+ body: dict | NewRelationshipRequestBody, optional, default = None
786
+ A structure representing the details of the relationship.
787
+
788
+ Returns
789
+ -------
790
+ Nothing
791
+
792
+ Raises
793
+ ------
794
+ PyegeriaInvalidParameterException
795
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
796
+ PyegeriaAPIException
797
+ Raised by the server when an issue arises in processing a valid request
798
+ NotAuthorizedException
799
+ The principle specified by the user_id does not have authorization for the requested action
800
+
801
+ Notes
802
+ -----
803
+ JSON Structure looks like:
804
+ {
805
+ "class" : "NewRelationshipRequestBody",
806
+ "externalSourceGUID": "add guid here",
807
+ "externalSourceName": "add qualified name here",
808
+ "effectiveTime" : "{{$isoTimestamp}}",
809
+ "forLineage" : false,
810
+ "forDuplicateProcessing" : false,
811
+ "properties": {
812
+ "class": "MediaReferenceProperties",
813
+ "mediaId": "",
814
+ "description": "",
815
+ "mediaUsage": "ICON",
816
+ "mediaUsageOtherId": "",
817
+ "effectiveFrom": "{{$isoTimestamp}}",
818
+ "effectiveTo": "{{$isoTimestamp}}"
819
+ }
820
+ }
821
+ """
822
+ loop = asyncio.get_event_loop()
823
+ loop.run_until_complete(self._async_link_media_reference(element_guid, media_ref_guid, body))
824
+
825
+ @dynamic_catch
826
+ async def _async_detach_media_reference(self, element_guid: str, media_ref_guid: str,
827
+ body: Optional[dict | DeleteRelationshipRequestBody] = None) -> None:
828
+ """ Detach an element from an external media reference; body is optional. Async version.
829
+
830
+ Parameters
831
+ ----------
832
+ element_guid: str
833
+ The unique identifier of the subscriber.
834
+ media_ref_guid: str
835
+ The unique identifier of the subscription.
836
+ body: dict | DeleteRelationshipRequestBody, optional, default = None
837
+ A structure representing the details of the relationship.
838
+
839
+ Returns
840
+ -------
841
+ Nothing
842
+
843
+ Raises
844
+ ------
845
+ PyegeriaInvalidParameterException
846
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
847
+ PyegeriaAPIException
848
+ Raised by the server when an issue arises in processing a valid request
849
+ NotAuthorizedException
850
+ The principle specified by the user_id does not have authorization for the requested action
851
+
852
+ Notes
853
+ -----
854
+ JSON Structure looks like:
855
+ {
856
+ "class": "DeleteRelationshipRequestBody",
857
+ "externalSourceGUID": "add guid here",
858
+ "externalSourceName": "add qualified name here",
859
+ "effectiveTime": "{{$isoTimestamp}}",
860
+ "forLineage": false,
861
+ "forDuplicateProcessing": false
862
+ }
863
+ """
864
+ url = (
865
+ f"{self.command_root}/elements/{element_guid}/media-references/{media_ref_guid}/detach")
866
+
867
+ await self._async_delete_relationship_request(url, body)
868
+ logger.info(f"Detached element {element_guid} from external media reference {media_ref_guid}")
869
+
870
+ @dynamic_catch
871
+ def detach_media_reference(self, element_guid: str, media_ref_guid: str, body: Optional[dict | DeleteRelationshipRequestBody] = None):
872
+ """ Detach an element from an external media reference. Request body is optional.
873
+
874
+ Parameters
875
+ ----------
876
+ element_guid: str
877
+ The unique identifier of the subscriber.
878
+ media_ref_guid: str
879
+ The unique identifier of the subscription.
880
+ body: dict, optional, default = None
881
+ A dict representing the details of the relationship.
882
+
883
+ Returns
884
+ -------
885
+ Nothing
886
+
887
+ Raises
888
+ ------
889
+ PyegeriaInvalidParameterException
890
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
891
+ PyegeriaAPIException
892
+ Raised by the server when an issue arises in processing a valid request
893
+ NotAuthorizedException
894
+ The principle specified by the user_id does not have authorization for the requested action
895
+
896
+ Notes
897
+ -----
898
+ JSON Structure looks like:
899
+ {
900
+ "class": "DeleteRelationshipRequestBody",
901
+ "externalSourceGUID": "add guid here",
902
+ "externalSourceName": "add qualified name here",
903
+ "effectiveTime": "{{$isoTimestamp}}",
904
+ "forLineage": false,
905
+ "forDuplicateProcessing": false
906
+ }
907
+ """
908
+ loop = asyncio.get_event_loop()
909
+ loop.run_until_complete(self._async_detach_media_reference(element_guid, media_ref_guid, body))
910
+
911
+ @dynamic_catch
912
+ async def _async_link_cited_document(self, element_guid: str, cited_doc_guid: str,
913
+ body: Optional[dict | NewRelationshipRequestBody] = None) -> None:
914
+ """ Attach an element to a cited document reference.
915
+ Async version.
916
+
917
+ Parameters
918
+ ----------
919
+ element_guid: str
920
+ The unique identifier of the element.
921
+ cited_doc_guid: str
922
+ The identifier of the external cited document reference.
923
+ body: dict | NewRelationshipRequestBody, optional, default = None
924
+ A structure representing the details of the relationship.
925
+
926
+ Returns
927
+ -------
928
+ Nothing
929
+
930
+ Raises
931
+ ------
932
+ PyegeriaInvalidParameterException
933
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
934
+ PyegeriaAPIException
935
+ Raised by the server when an issue arises in processing a valid request
936
+ NotAuthorizedException
937
+ The principle specified by the user_id does not have authorization for the requested action
938
+
939
+ Notes
940
+ -----
941
+ JSON Structure looks like:
942
+ {
943
+ "class" : "NewRelationshipRequestBody",
944
+ "externalSourceGUID": "add guid here",
945
+ "externalSourceName": "add qualified name here",
946
+ "effectiveTime" : "{{$isoTimestamp}}",
947
+ "forLineage" : false,
948
+ "forDuplicateProcessing" : false,
949
+ "properties": {
950
+ "class": "CitedDocumentLinkProperties",
951
+ "referenceId": "add reference id here",
952
+ "description": "Add description of the external_reference here",
953
+ "pages": "Add pages here"
954
+ }
955
+ }
956
+ """
957
+ url = f"{self.command_root}/elements/{element_guid}/cited-document-references/{cited_doc_guid}/attach"
958
+ await self._async_new_relationship_request(url, "CitedDocumentLinkProperties", body)
959
+ logger.info(f"Linking element {element_guid} to cited document {cited_doc_guid}")
960
+
961
+ @dynamic_catch
962
+ def link_cited_document(self, element_guid: str, cited_doc_guid: str,
963
+ body: Optional[dict | NewRelationshipRequestBody] = None):
964
+ """ Attach an element to an external media reference.
965
+
966
+ Parameters
967
+ ----------
968
+ element_guid: str
969
+ The unique identifier of the element.
970
+ cited_doc_guid: str
971
+ The identifier of the external reference.
972
+ body: dict | NewRelationshipRequestBody, optional, default = None
973
+ A structure representing the details of the relationship.
974
+
975
+ Returns
976
+ -------
977
+ Nothing
978
+
979
+ Raises
980
+ ------
981
+ PyegeriaInvalidParameterException
982
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
983
+ PyegeriaAPIException
984
+ Raised by the server when an issue arises in processing a valid request
985
+ NotAuthorizedException
986
+ The principle specified by the user_id does not have authorization for the requested action
987
+
988
+ Notes
989
+ -----
990
+ JSON Structure looks like:
991
+ {
992
+ "class" : "NewRelationshipRequestBody",
993
+ "externalSourceGUID": "add guid here",
994
+ "externalSourceName": "add qualified name here",
995
+ "effectiveTime" : "{{$isoTimestamp}}",
996
+ "forLineage" : false,
997
+ "forDuplicateProcessing" : false,
998
+ "properties": {
999
+ "class": "CitedDocumentLinkProperties",
1000
+ "referenceId": "add reference id here",
1001
+ "description": "Add description of the external_reference here",
1002
+ "pages": "Add pages here"
1003
+ }
1004
+ }
1005
+ """
1006
+ loop = asyncio.get_event_loop()
1007
+ loop.run_until_complete(self._async_link_cited_document(element_guid, cited_doc_guid, body))
1008
+
1009
+ @dynamic_catch
1010
+ async def _async_detach_cited_document(self, element_guid: str, cited_doc_guid: str,
1011
+ body: Optional[dict | DeleteRelationshipRequestBody] = None) -> None:
1012
+ """ Detach an element from an cited document reference; body is optional. Async version.
1013
+
1014
+ Parameters
1015
+ ----------
1016
+ element_guid: str
1017
+ The unique identifier of the subscriber.
1018
+ cited_doc_guid: str
1019
+ The unique identifier of the subscription.
1020
+ body: dict | DeleteRelationshipRequestBody, optional, default = None
1021
+ A structure representing the details of the relationship.
1022
+
1023
+ Returns
1024
+ -------
1025
+ Nothing
1026
+
1027
+ Raises
1028
+ ------
1029
+ PyegeriaInvalidParameterException
1030
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1031
+ PyegeriaAPIException
1032
+ Raised by the server when an issue arises in processing a valid request
1033
+ NotAuthorizedException
1034
+ The principle specified by the user_id does not have authorization for the requested action
1035
+
1036
+ Notes
1037
+ -----
1038
+ JSON Structure looks like:
1039
+ {
1040
+ "class": "DeleteRelationshipRequestBody",
1041
+ "externalSourceGUID": "add guid here",
1042
+ "externalSourceName": "add qualified name here",
1043
+ "effectiveTime": "{{$isoTimestamp}}",
1044
+ "forLineage": false,
1045
+ "forDuplicateProcessing": false
1046
+ }
1047
+ """
1048
+ url = f"{self.command_root}/elements/{element_guid}/cited-document-references/{cited_doc_guid}/detach"
1049
+
1050
+ await self._async_delete_relationship_request(url, body)
1051
+ logger.info(f"Detached element {element_guid} from cited document reference {cited_doc_guid}")
1052
+
1053
+ @dynamic_catch
1054
+ def detach_cited_document(self, element_guid: str, cited_doc_guid: str, body: Optional[dict | DeleteRelationshipRequestBody] = None):
1055
+ """ Detach an element from acited document reference. Request body is optional.
1056
+
1057
+ Parameters
1058
+ ----------
1059
+ element_guid: str
1060
+ The unique identifier of the subscriber.
1061
+ cited_doc_guid: str
1062
+ The unique identifier of the subscription.
1063
+ body: dict, optional, default = None
1064
+ A dict representing the details of the relationship.
1065
+
1066
+ Returns
1067
+ -------
1068
+ Nothing
1069
+
1070
+ Raises
1071
+ ------
1072
+ PyegeriaInvalidParameterException
1073
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1074
+ PyegeriaAPIException
1075
+ Raised by the server when an issue arises in processing a valid request
1076
+ NotAuthorizedException
1077
+ The principle specified by the user_id does not have authorization for the requested action
1078
+
1079
+ Notes
1080
+ -----
1081
+ JSON Structure looks like:
1082
+ {
1083
+ "class": "DeleteRelationshipRequestBody",
1084
+ "externalSourceGUID": "add guid here",
1085
+ "externalSourceName": "add qualified name here",
1086
+ "effectiveTime": "{{$isoTimestamp}}",
1087
+ "forLineage": false,
1088
+ "forDuplicateProcessing": false
1089
+ }
1090
+ """
1091
+ loop = asyncio.get_event_loop()
1092
+ loop.run_until_complete(self._async_detach_cited_document(element_guid, cited_doc_guid, body))
1093
+
1094
+ #
1095
+ # do deletes etc
1096
+ #
1097
+ @dynamic_catch
1098
+ async def _async_delete_external_reference(self, ext_ref_guid: str,
1099
+ body: Optional[dict | DeleteRelationshipRequestBody] = None,
1100
+ cascade: bool = False) -> None:
1101
+ """ Delete an external reference. Async Version.
1102
+
1103
+ Parameters
1104
+ ----------
1105
+ ext_ref_guid: str
1106
+ The guid of the governance definition to delete.
1107
+
1108
+ cascade: bool, optional, defaults to True
1109
+ If true, a cascade delete is performed.
1110
+
1111
+ body: dict DeleteRelationshipRequestBodyt, optional, default = None
1112
+ A dict representing the details of the relationship.
1113
+
1114
+ Returns
1115
+ -------
1116
+ Nothing
1117
+
1118
+ Raises
1119
+ ------
1120
+ PyegeriaInvalidParameterException
1121
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1122
+ ValidationException
1123
+ Raised by pydantic when the request body is invalid.
1124
+ NotAuthorizedException
1125
+ The principle specified by the user_id does not have authorization for the requested action
1126
+
1127
+ Notes
1128
+ _____
1129
+ JSON Structure looks like:
1130
+ {
1131
+ "class" : "DeleteRelationshipRequestBody",
1132
+ "externalSourceGUID": "add guid here",
1133
+ "externalSourceName": "add qualified name here",
1134
+ "effectiveTime" : "{{$isoTimestamp}}",
1135
+ "forLineage" : false,
1136
+ "forDuplicateProcessing" : false
1137
+ }
1138
+ """
1139
+ url = f"{self.command_root}/external-references/{ext_ref_guid}/delete"
1140
+
1141
+ await self._async_delete_element_request(url, body, cascade)
1142
+ logger.info(f"Deleted collection {ext_ref_guid} with cascade {cascade}")
1143
+
1144
+ @dynamic_catch
1145
+ def delete_external_reference(self, ext_ref_guid: str, body: Optional[dict | DeleteElementRequestBody] = None,
1146
+ cascade: bool = False) -> None:
1147
+ """Delete an external reference..
1148
+
1149
+ Parameters
1150
+ ----------
1151
+ ext_ref_guid: str
1152
+ The guid of the external reference to delete.
1153
+
1154
+ cascade: bool, optional, defaults to True
1155
+ If true, a cascade delete is performed.
1156
+
1157
+ body: dict DeleteElementRequestBody, optional, default = None
1158
+ A dict representing the details of the relationship.
1159
+
1160
+ Returns
1161
+ -------
1162
+ Nothing
1163
+
1164
+ Raises
1165
+ ------
1166
+ PyegeriaInvalidParameterException
1167
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1168
+ ValidationException
1169
+ Raised by pydantic when the request body is invalid.
1170
+ NotAuthorizedException
1171
+ The principle specified by the user_id does not have authorization for the requested action
1172
+
1173
+ Notes
1174
+ _____
1175
+ JSON Structure looks like:
1176
+ {
1177
+ "class" : "DeleteElementRequestBody",
1178
+ "externalSourceGUID": "add guid here",
1179
+ "externalSourceName": "add qualified name here",
1180
+ "effectiveTime" : "{{$isoTimestamp}}",
1181
+ "forLineage" : false,
1182
+ "forDuplicateProcessing" : false
1183
+ }
1184
+ """
1185
+ loop = asyncio.get_event_loop()
1186
+ loop.run_until_complete(self._async_delete_external_reference(ext_ref_guid, body, cascade))
1187
+
1188
+ @dynamic_catch
1189
+ async def _async_find_external_references(self, search_string: str = "*",
1190
+ starts_with: bool = True, ends_with: bool = False,
1191
+ ignore_case: bool = False,
1192
+ anchor_domain: Optional[str] = None,
1193
+ metadata_element_type: Optional[str] = None,
1194
+ metadata_element_subtypes: list[str] = EXTERNAL_REFERENCE_TYPES,
1195
+ skip_relationships: Optional[list[str]] = None,
1196
+ include_only_relationships: Optional[list[str]] = None,
1197
+ skip_classified_elements: Optional[list[str]] = None,
1198
+ include_only_classified_elements: Optional[list[str]] = None,
1199
+ graph_query_depth: int = 3,
1200
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
1201
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
1202
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
1203
+ sequencing_property: Optional[str] = None,
1204
+ output_format: str = 'JSON',
1205
+ report_spec: str | dict = "ExternalReference",
1206
+ start_from: int = 0, page_size: int = 100,
1207
+ property_names: Optional[list[str]] = None,
1208
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
1209
+ """ Retrieve the list of external reference metadata elements that contain the search string. Async Version.
1210
+
1211
+ Parameters
1212
+ ----------
1213
+ search_string: str
1214
+ Search string to match against - None or '*' indicate match against all external references.
1215
+ starts_with : bool, [default=True], optional
1216
+ Starts with the supplied string.
1217
+ ends_with : bool, [default=False], optional
1218
+ Ends with the supplied string
1219
+ ignore_case : bool, [default=False], optional
1220
+ Ignore case when searching
1221
+ anchor_domain: str, optional
1222
+ The anchor domain to search in.
1223
+ metadata_element_type: str, optional
1224
+ The type of metadata element to search for.
1225
+ metadata_element_subtypes: list[str], optional
1226
+ The subtypes of metadata element to search for.
1227
+ skip_relationships: list[str], optional
1228
+ The types of relationships to skip.
1229
+ include_only_relationships: list[str], optional
1230
+ The types of relationships to include.
1231
+ skip_classified_elements: list[str], optional
1232
+ The types of classified elements to skip.
1233
+ include_only_classified_elements: list[str], optional
1234
+ The types of classified elements to include.
1235
+ graph_query_depth: int, [default=3], optional
1236
+ The depth of the graph query.
1237
+ governance_zone_filter: list[str], optional
1238
+ The governance zones to search in.
1239
+ as_of_time: str, optional
1240
+ The time to search as of.
1241
+ effective_time: str, optional
1242
+ The effective time to search at.
1243
+ relationship_page_size: int, [default=0], optional
1244
+ The page size for relationships.
1245
+ limit_results_by_status: list[str], optional
1246
+ The statuses to limit results by.
1247
+ sequencing_order: str, optional
1248
+ The order to sequence results by.
1249
+ sequencing_property: str, optional
1250
+ The property to sequence results by.
1251
+ output_format: str, default = "JSON"
1252
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
1253
+ report_spec: str | dict , optional, default = "ExternalReference"
1254
+ - The desired output columns/fields to include.
1255
+ start_from: int, [default=0], optional
1256
+ When multiple pages of results are available, the page number to start from.
1257
+ page_size: int, [default=100]
1258
+ The number of items to return in a single page.
1259
+ property_names: list[str], optional
1260
+ The names of properties to search for.
1261
+ body: dict | SearchStringRequestBody, optional, default = None
1262
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
1263
+
1264
+ Returns
1265
+ -------
1266
+ List | str
1267
+
1268
+ Output depends on the output format specified.
1269
+
1270
+ Raises
1271
+ ------
1272
+
1273
+ ValidationError
1274
+ If the client passes incorrect parameters on the request that don't conform to the data model.
1275
+ PyegeriaException
1276
+ Issues raised in communicating or server side processing.
1277
+ NotAuthorizedException
1278
+ The principle specified by the user_id does not have authorization for the requested action
1279
+
1280
+ """
1281
+ url = str(HttpUrl(f"{self.command_root}/external-references/by-search-string"))
1282
+ response = await self._async_find_request(url, _type="ExternalReference",
1283
+ _gen_output=self._generate_external_reference_output,
1284
+ search_string=search_string, starts_with=starts_with,
1285
+ ends_with=ends_with, ignore_case=ignore_case,
1286
+ anchor_domain=anchor_domain,
1287
+ metadata_element_type=metadata_element_type,
1288
+ metadata_element_subtypes=metadata_element_subtypes,
1289
+ skip_relationships=skip_relationships,
1290
+ include_only_relationships=include_only_relationships,
1291
+ skip_classified_elements=skip_classified_elements,
1292
+ include_only_classified_elements=include_only_classified_elements,
1293
+ graph_query_depth=graph_query_depth,
1294
+ governance_zone_filter=governance_zone_filter,
1295
+ as_of_time=as_of_time, effective_time=effective_time,
1296
+ relationship_page_size=relationship_page_size,
1297
+ limit_results_by_status=limit_results_by_status,
1298
+ sequencing_order=sequencing_order,
1299
+ sequencing_property=sequencing_property,
1300
+ output_format=output_format, report_spec=report_spec,
1301
+ start_from=start_from, page_size=page_size,
1302
+ property_names=property_names, body=body)
1303
+
1304
+ return response
1305
+
1306
+ @dynamic_catch
1307
+ def find_external_references(self, search_string: str = "*",
1308
+ starts_with: bool = True, ends_with: bool = False,
1309
+ ignore_case: bool = False,
1310
+ anchor_domain: Optional[str] = None,
1311
+ metadata_element_type: Optional[str] = None,
1312
+ metadata_element_subtypes: list[str] = EXTERNAL_REFERENCE_TYPES,
1313
+ skip_relationships: Optional[list[str]] = None,
1314
+ include_only_relationships: Optional[list[str]] = None,
1315
+ skip_classified_elements: Optional[list[str]] = None,
1316
+ include_only_classified_elements: Optional[list[str]] = None,
1317
+ graph_query_depth: int = 3,
1318
+ governance_zone_filter: Optional[list[str]] = None, as_of_time: Optional[str] = None,
1319
+ effective_time: Optional[str] = None, relationship_page_size: int = 0,
1320
+ limit_results_by_status: Optional[list[str]] = None, sequencing_order: Optional[str] = None,
1321
+ sequencing_property: Optional[str] = None,
1322
+ output_format: str = 'JSON',
1323
+ report_spec: str | dict = "ExternalReference",
1324
+ start_from: int = 0, page_size: int = 100,
1325
+ property_names: Optional[list[str]] = None,
1326
+ body: Optional[dict | SearchStringRequestBody] = None) -> list | str:
1327
+ """ Retrieve the list of external reference metadata elements that contain the search string.
1328
+
1329
+ Parameters
1330
+ ----------
1331
+ search_string: str
1332
+ Search string to match against - None or '*' indicate match against all external references.
1333
+ starts_with : bool, [default=True], optional
1334
+ Starts with the supplied string.
1335
+ ends_with : bool, [default=False], optional
1336
+ Ends with the supplied string
1337
+ ignore_case : bool, [default=False], optional
1338
+ Ignore case when searching
1339
+ anchor_domain: str, optional
1340
+ The anchor domain to search in.
1341
+ metadata_element_type: str, optional
1342
+ The type of metadata element to search for.
1343
+ metadata_element_subtypes: list[str], optional
1344
+ The subtypes of metadata element to search for.
1345
+ skip_relationships: list[str], optional
1346
+ The types of relationships to skip.
1347
+ include_only_relationships: list[str], optional
1348
+ The types of relationships to include.
1349
+ skip_classified_elements: list[str], optional
1350
+ The types of classified elements to skip.
1351
+ include_only_classified_elements: list[str], optional
1352
+ The types of classified elements to include.
1353
+ graph_query_depth: int, [default=3], optional
1354
+ The depth of the graph query.
1355
+ governance_zone_filter: list[str], optional
1356
+ The governance zones to search in.
1357
+ as_of_time: str, optional
1358
+ The time to search as of.
1359
+ effective_time: str, optional
1360
+ The effective time to search at.
1361
+ relationship_page_size: int, [default=0], optional
1362
+ The page size for relationships.
1363
+ limit_results_by_status: list[str], optional
1364
+ The statuses to limit results by.
1365
+ sequencing_order: str, optional
1366
+ The order to sequence results by.
1367
+ sequencing_property: str, optional
1368
+ The property to sequence results by.
1369
+ output_format: str, default = "JSON"
1370
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
1371
+ report_spec: str | dict , optional, default = "ExternalReference"
1372
+ - The desired output columns/fields to include.
1373
+ start_from: int, [default=0], optional
1374
+ When multiple pages of results are available, the page number to start from.
1375
+ page_size: int, [default=100]
1376
+ The number of items to return in a single page.
1377
+ property_names: list[str], optional
1378
+ The names of properties to search for.
1379
+ body: dict | SearchStringRequestBody, optional, default = None
1380
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
1381
+
1382
+ Returns
1383
+ -------
1384
+ List | str
1385
+
1386
+ Output depends on the output format specified.
1387
+
1388
+ Raises
1389
+ -------
1390
+
1391
+ ValidationError
1392
+ If the client passes incorrect parameters on the request that don't conform to the data model.
1393
+ PyegeriaException
1394
+ Issues raised in communicating or server side processing.
1395
+ NotAuthorizedException
1396
+ The principle specified by the user_id does not have authorization for the requested action
1397
+
1398
+ """
1399
+ loop = asyncio.get_event_loop()
1400
+ return loop.run_until_complete(self._async_find_external_references(search_string=search_string,
1401
+ starts_with=starts_with,
1402
+ ends_with=ends_with,
1403
+ ignore_case=ignore_case,
1404
+ anchor_domain=anchor_domain,
1405
+ metadata_element_type=metadata_element_type,
1406
+ metadata_element_subtypes=metadata_element_subtypes,
1407
+ skip_relationships=skip_relationships,
1408
+ include_only_relationships=include_only_relationships,
1409
+ skip_classified_elements=skip_classified_elements,
1410
+ include_only_classified_elements=include_only_classified_elements,
1411
+ graph_query_depth=graph_query_depth,
1412
+ governance_zone_filter=governance_zone_filter,
1413
+ as_of_time=as_of_time,
1414
+ effective_time=effective_time,
1415
+ relationship_page_size=relationship_page_size,
1416
+ limit_results_by_status=limit_results_by_status,
1417
+ sequencing_order=sequencing_order,
1418
+ sequencing_property=sequencing_property,
1419
+ output_format=output_format,
1420
+ report_spec=report_spec,
1421
+ start_from=start_from,
1422
+ page_size=page_size,
1423
+ property_names=property_names,
1424
+ body=body))
1425
+
1426
+ @dynamic_catch
1427
+ async def _async_get_external_references_by_name(self, filter_string: Optional[str] = None,
1428
+ classification_names: Optional[list[str]] = None,
1429
+ body: Optional[dict | FilterRequestBody] = None,
1430
+ start_from: int = 0, page_size: int = 0,
1431
+ output_format: str = 'JSON',
1432
+ report_spec: str | dict = "ExternalReference") -> list | str:
1433
+ """ Returns the list of external references with a particular name.
1434
+
1435
+ Parameters
1436
+ ----------
1437
+ filter_string: str,
1438
+ name to use to find matching collections.
1439
+ classification_names: list[str], optional, default = None
1440
+ type of collection to filter by - e.g., DataDict, Folder, Root
1441
+ body: dict, optional, default = None
1442
+ Provides, a full request body. If specified, the body supercedes the name parameter.
1443
+ start_from: int, [default=0], optional
1444
+ When multiple pages of results are available, the page number to start from.
1445
+ page_size: int, [default=None]
1446
+ The number of items to return in a single page. If not specified, the default will be taken from
1447
+ the class instance.
1448
+ output_format: str, default = "JSON"
1449
+ - one of "DICT", "MERMAID" or "JSON"
1450
+ report_spec: dict , optional, default = None
1451
+ The desired output columns/fields to include.
1452
+
1453
+ Returns
1454
+ -------
1455
+ List | str
1456
+
1457
+ A list of collections match matching the name. Returns a string if none found.
1458
+
1459
+ Raises
1460
+ ------
1461
+
1462
+ PyegeriaInvalidParameterException
1463
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1464
+ PyegeriaAPIException
1465
+ Raised by the server when an issue arises in processing a valid request
1466
+ NotAuthorizedException
1467
+ The principle specified by the user_id does not have authorization for the requested action
1468
+ """
1469
+ url = str(HttpUrl(f"{self.command_root}/external-references/by-name"))
1470
+ response = await self._async_get_name_request(url, _type="ExternalReference",
1471
+ _gen_output=self._generate_external_reference_output,
1472
+ filter_string=filter_string,
1473
+ classification_names=classification_names,
1474
+ start_from=start_from, page_size=page_size,
1475
+ output_format=output_format, report_spec=report_spec,
1476
+ body=body)
1477
+
1478
+ return response
1479
+
1480
+ def get_external_references_by_name(self, filter_string: Optional[str] = None, classification_names: Optional[list[str]] = None,
1481
+ body: Optional[dict | FilterRequestBody] = None,
1482
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
1483
+ report_spec: str | dict = "ExternalReference") -> list | str:
1484
+ """Returns the list of external references matching the filter string. Async version.
1485
+ The search string is located in the request body and is interpreted as a plain string.
1486
+ The request parameters, startsWith, endsWith, and ignoreCase can be used to allow a fuzzy search.
1487
+
1488
+ Parameters
1489
+ ----------
1490
+ filter_string: str,
1491
+ name to use to find matching collections.
1492
+ classification_names: list[str], optional, default = None
1493
+ type of collection to filter by - e.g., DataDict, Folder, Root
1494
+ body: dict, optional, default = None
1495
+ Provides, a full request body. If specified, the body supercedes the name parameter.
1496
+ start_from: int, [default=0], optional
1497
+ When multiple pages of results are available, the page number to start from.
1498
+ page_size: int, [default=None]
1499
+ The number of items to return in a single page. If not specified, the default will be taken from
1500
+ the class instance.
1501
+ output_format: str, default = "JSON"
1502
+ - one of "DICT", "MERMAID" or "JSON"
1503
+ report_spec: str | dict, optional, default = None
1504
+ The desired output columns/fields to include.
1505
+
1506
+ Returns
1507
+ -------
1508
+ List | str
1509
+
1510
+ A list of collections match matching the search string. Returns a string if none found.
1511
+
1512
+ Raises
1513
+ ------
1514
+ PyegeriaException
1515
+
1516
+ """
1517
+ return asyncio.get_event_loop().run_until_complete(
1518
+ self._async_get_external_references_by_name(filter_string, classification_names, body, start_from,
1519
+ page_size,
1520
+ output_format, report_spec))
1521
+
1522
+ @dynamic_catch
1523
+ async def _async_get_external_reference_by_guid(self, ext_ref_guid: str, element_type: Optional[str] = None,
1524
+ body: Optional[dict | GetRequestBody] = None,
1525
+ output_format: str = 'JSON',
1526
+ report_spec: str | dict = "ExternalReference") -> dict | str:
1527
+ """Return the properties of a specific external reference. Async version.
1528
+
1529
+ Parameters
1530
+ ----------
1531
+ ext_ref_guid: str,
1532
+ unique identifier of the external reference to retrieve.
1533
+ element_type: str, default = None, optional
1534
+ type of externak reference ExternalReference, RelatedMedia, etc.
1535
+ body: dict | GetRequestBody, optional, default = None
1536
+ full request body.
1537
+ output_format: str, default = "JSON"
1538
+ - one of "DICT", "MERMAID" or "JSON"
1539
+ report_spec: str | dict, optional, default = None
1540
+ The desired output columns/fields to include.
1541
+
1542
+ Returns
1543
+ -------
1544
+ dict | str
1545
+
1546
+ A JSON dict representing the specified collection. Returns a string if none found.
1547
+
1548
+ Raises
1549
+ ------
1550
+
1551
+ PyegeriaInvalidParameterException
1552
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1553
+ PyegeriaAPIException
1554
+ Raised by the server when an issue arises in processing a valid request
1555
+ NotAuthorizedException
1556
+ The principle specified by the user_id does not have authorization for the requested action
1557
+
1558
+ Notes
1559
+ ----
1560
+ Body sample:
1561
+ {
1562
+ "class": "GetRequestBody",
1563
+ "asOfTime": "{{$isoTimestamp}}",
1564
+ "effectiveTime": "{{$isoTimestamp}}",
1565
+ "forLineage": false,
1566
+ "forDuplicateProcessing": false
1567
+ }
1568
+ """
1569
+
1570
+ url = str(HttpUrl(f"{self.command_root}/external-references/{ext_ref_guid}/retrieve"))
1571
+ type = element_type if element_type else "ExternalReference"
1572
+
1573
+ response = await self._async_get_guid_request(url, _type=type,
1574
+ _gen_output=self._generate_external_reference_output,
1575
+ output_format=output_format, report_spec=report_spec,
1576
+ body=body)
1577
+
1578
+ return response
1579
+
1580
+ @dynamic_catch
1581
+ def get_external_reference_by_guid(self, ext_ref_guid: str, element_type: Optional[str] = None,
1582
+ body: Optional[dict | GetRequestBody] = None,
1583
+ output_format: str = 'JSON',
1584
+ report_spec: str | dict = "ExternalReference") -> dict | str:
1585
+ """ Return the properties of a specific external reference. Async version.
1586
+
1587
+ Parameters
1588
+ ----------
1589
+ ext_ref_guid: str,
1590
+ unique identifier of the external reference to retrieve.
1591
+ element_type: str, default = None, optional
1592
+ type of element - ExternalReference, RelatedMedia, etc.
1593
+ body: dict | GetRequestBody, optional, default = None
1594
+ full request body.
1595
+ output_format: str, default = "JSON"
1596
+ - one of "DICT", "MERMAID" or "JSON"
1597
+ report_spec: dict , optional, default = None
1598
+ The desired output columns/fields to include.
1599
+
1600
+
1601
+ Returns
1602
+ -------
1603
+ dict | str
1604
+
1605
+ A JSON dict representing the specified collection. Returns a string if none found.
1606
+
1607
+ Raises
1608
+ ------
1609
+
1610
+ PyegeriaInvalidParameterException
1611
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1612
+ PyegeriaAPIException
1613
+ Raised by the server when an issue arises in processing a valid request
1614
+ NotAuthorizedException
1615
+ The principle specified by the user_id does not have authorization for the requested action
1616
+
1617
+ Notes
1618
+ ----
1619
+ Body sample:
1620
+ {
1621
+ "class": "AnyTimeRequestBody",
1622
+ "asOfTime": "{{$isoTimestamp}}",
1623
+ "effectiveTime": "{{$isoTimestamp}}",
1624
+ "forLineage": false,
1625
+ "forDuplicateProcessing": false
1626
+ }
1627
+ """
1628
+ return asyncio.get_event_loop().run_until_complete(
1629
+ self._async_get_external_reference_by_guid(ext_ref_guid, element_type, body,
1630
+ output_format, report_spec))
1631
+
1632
+ def _extract_external_reference_properties(self, element: dict, columns_struct: dict) -> dict:
1633
+ """
1634
+ Extract common properties from a external_reference element and populate into the provided columns_struct.
1635
+
1636
+ Args:
1637
+ element (dict): The external_reference element
1638
+ columns_struct (dict): The columns structure to populate
1639
+
1640
+ Returns:
1641
+ dict: columns_struct with column 'value' fields populated
1642
+ """
1643
+ # First, populate from element.properties using the utility
1644
+ col_data = populate_columns_from_properties(element, columns_struct)
1645
+
1646
+ columns_list = col_data.get("formats", {}).get("attributes", [])
1647
+
1648
+ # Populate header-derived values
1649
+ header_props = _extract_referenceable_properties(element)
1650
+ for column in columns_list:
1651
+ key = column.get('key')
1652
+ if key in header_props:
1653
+ column['value'] = header_props.get(key)
1654
+ elif isinstance(key, str) and key.lower() == 'guid':
1655
+ column['value'] = header_props.get('GUID')
1656
+
1657
+ # Derived/computed fields
1658
+ # external_referenceCategories are classifications
1659
+ classification_names = ""
1660
+ classifications = element.get('elementHeader', {}).get("external_referenceCategories", [])
1661
+ for classification in classifications:
1662
+ classification_names += f"{classification['classificationName']}, "
1663
+ if classification_names:
1664
+ for column in columns_list:
1665
+ if column.get('key') == 'classifications':
1666
+ column['value'] = classification_names[:-2]
1667
+ break
1668
+
1669
+ # Populate requested relationship-based columns generically from top-level keys
1670
+ col_data = get_required_relationships(element, col_data)
1671
+
1672
+ # Subject area classification
1673
+ subject_area = element.get('elementHeader', {}).get("subjectArea", "") or ""
1674
+ subj_val = ""
1675
+ if isinstance(subject_area, dict):
1676
+ subj_val = subject_area.get("classificationProperties", {}).get("subjectAreaName", "")
1677
+ for column in columns_list:
1678
+ if column.get('key') == 'subject_area':
1679
+ column['value'] = subj_val
1680
+ break
1681
+
1682
+ # Mermaid graph
1683
+ mermaid_val = element.get('mermaidGraph', "") or ""
1684
+ for column in columns_list:
1685
+ if column.get('key') == 'mermaid':
1686
+ column['value'] = mermaid_val
1687
+ break
1688
+
1689
+ logger.trace(f"Extracted/Populated columns: {col_data}")
1690
+
1691
+ return col_data
1692
+
1693
+ def _generate_external_reference_output(self, elements: dict | list[dict], filter_string: Optional[str],
1694
+ element_type_name: Optional[str], output_format: str = "DICT",
1695
+ report_spec: dict | str = None) -> str | list[dict]:
1696
+ """ Generate output for external_references in the specified format.
1697
+
1698
+ Args:
1699
+ elements (Union[Dict, List[Dict]]): Dictionary or list of dictionaries containing data field elements
1700
+ filter (Optional[str]): The search string used to find the elements
1701
+ element_type_name (Optional[str]): The type of external_reference
1702
+ output_format (str): The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID, HTML)
1703
+ report_spec (Optional[dict], optional): List of dictionaries containing column data. Defaults
1704
+ to None.
1705
+
1706
+ Returns:
1707
+ Union[str, List[Dict]]: Formatted output as a string or list of dictionaries
1708
+ """
1709
+ if element_type_name is None:
1710
+ entity_type = "ExternalReference"
1711
+ else:
1712
+ entity_type = element_type_name
1713
+ # First see if the user has specified an report_spec - either a label or a dict
1714
+ get_additional_props_func = None
1715
+ if report_spec:
1716
+ if isinstance(report_spec, str):
1717
+ output_formats = select_report_spec(report_spec, output_format)
1718
+ elif isinstance(report_spec, dict):
1719
+ output_formats = get_report_spec_match(report_spec, output_format)
1720
+
1721
+ # If no output_format was set, then use the element_type_name to lookup the output format
1722
+ elif element_type_name:
1723
+ output_formats = select_report_spec(element_type_name, output_format)
1724
+ else:
1725
+ # fallback to external_references or entity type
1726
+ output_formats = select_report_spec(entity_type, output_format)
1727
+ if output_formats is None:
1728
+ output_formats = select_report_spec("Default", output_format)
1729
+
1730
+ if output_formats:
1731
+ get_additional_props_name = output_formats.get("get_additional_props", {}).get("function", None)
1732
+ if isinstance(get_additional_props_name, str):
1733
+ class_name, method_name = get_additional_props_name.split(".")
1734
+ if hasattr(self, method_name):
1735
+ get_additional_props_func = getattr(self, method_name)
1736
+
1737
+ logger.trace(f"Executing generate_external_reference_output for {entity_type}: {output_formats}")
1738
+ return generate_output(
1739
+ elements,
1740
+ filter,
1741
+ entity_type,
1742
+ output_format,
1743
+ self._extract_external_reference_properties,
1744
+ get_additional_props_func,
1745
+ output_formats,
1746
+ )
1747
+
1748
+
1749
+ from typing import Union, Dict, List, Optional
1750
+
1751
+ if __name__ == "__main__":
1752
+ print("Main-Collection Manager")