pyegeria 5.4.3.3__py3-none-any.whl → 5.4.4__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.
Files changed (230) hide show
  1. commands/cat/debug_log.2025-09-02_07-44-39_567276.log.zip +0 -0
  2. commands/cat/debug_log.2025-09-03_07-45-21_986388.log.zip +0 -0
  3. commands/cat/debug_log.2025-09-04_08-21-58_788009.log.zip +0 -0
  4. commands/cat/debug_log.2025-09-05_09-37-53_062579.log.zip +0 -0
  5. commands/cat/list_format_set.py +5 -3
  6. commands/tech/list_information_supply_chains.py +1 -1
  7. commands/tech/list_solution_blueprints.py +1 -1
  8. commands/tech/list_solution_components.py +1 -1
  9. commands/tech/list_solution_roles.py +1 -1
  10. md_processing/__init__.py +9 -5
  11. md_processing/data/commands.json +7182 -1401
  12. md_processing/data/generated_format_sets.json +4137 -0
  13. md_processing/data/generated_format_sets.py +51 -0
  14. md_processing/dr_egeria.py +20 -11
  15. md_processing/md_commands/data_designer_commands.py +90 -425
  16. md_processing/md_commands/ext_ref_commands.py +543 -0
  17. md_processing/md_commands/old_solution_architect_commands.py +1139 -0
  18. md_processing/md_commands/solution_architect_commands.py +26 -59
  19. md_processing/md_processing_utils/common_md_utils.py +50 -1
  20. md_processing/md_processing_utils/debug_log +1 -3
  21. md_processing/md_processing_utils/dr-egeria-help-2025-09-09T11:10:03.md +3305 -0
  22. md_processing/md_processing_utils/extraction_utils.py +14 -7
  23. md_processing/md_processing_utils/gen_format_sets.py +422 -0
  24. md_processing/md_processing_utils/md_processing_constants.py +20 -2
  25. pyegeria/__init__.py +1 -1
  26. pyegeria/_client_new.py +9 -7
  27. pyegeria/_output_formats.py +278 -3
  28. pyegeria/collection_manager.py +20 -59
  29. pyegeria/config.py +10 -1
  30. pyegeria/data_designer.py +166 -117
  31. pyegeria/egeria_client.py +1 -1
  32. pyegeria/egeria_tech_client.py +4 -1
  33. pyegeria/external_references.py +1794 -0
  34. pyegeria/glossary_manager.py +71 -85
  35. pyegeria/governance_officer.py +26 -29
  36. pyegeria/output_formatter.py +127 -1
  37. pyegeria/project_manager.py +33 -36
  38. pyegeria/{solution_architect_omvs.py → solution_architect.py} +733 -873
  39. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/METADATA +1 -1
  40. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/RECORD +43 -219
  41. commands/.DS_Store +0 -0
  42. commands/cat/.DS_Store +0 -0
  43. commands/cat/.env +0 -8
  44. commands/cat/debug_log.2025-08-29_07-07-27_848189.log.zip +0 -0
  45. commands/cat/debug_log.2025-08-30_21-15-48_528443.log.zip +0 -0
  46. commands/cat/debug_log.log +0 -6102
  47. commands/cat/logs/pyegeria.log +0 -90
  48. commands/cli/debug_log.log +0 -0
  49. commands/doc/.DS_Store +0 -0
  50. commands/ops/logs/pyegeria.log +0 -0
  51. md_processing/.DS_Store +0 -0
  52. md_processing/.idea/.gitignore +0 -8
  53. md_processing/.idea/inspectionProfiles/Project_Default.xml +0 -59
  54. md_processing/.idea/md_processing.iml +0 -15
  55. md_processing/.idea/modules.xml +0 -8
  56. md_processing/.idea/sonarlint/issuestore/index.pb +0 -0
  57. md_processing/.idea/sonarlint/securityhotspotstore/index.pb +0 -0
  58. md_processing/.idea/vcs.xml +0 -6
  59. md_processing/.idea/workspace.xml +0 -107
  60. md_processing/dr_egeria_inbox/Derive-Dr-Gov-Defs.md +0 -8
  61. md_processing/dr_egeria_inbox/Dr.Egeria Templates.md +0 -873
  62. md_processing/dr_egeria_inbox/arch_test.md +0 -57
  63. md_processing/dr_egeria_inbox/archive/dr_egeria_intro.md +0 -254
  64. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_more_terms.md +0 -696
  65. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part1.md +0 -254
  66. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part2.md +0 -298
  67. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part3.md +0 -608
  68. md_processing/dr_egeria_inbox/archive/dr_egeria_intro_part4.md +0 -94
  69. md_processing/dr_egeria_inbox/archive/freddie_intro.md +0 -284
  70. md_processing/dr_egeria_inbox/archive/freddie_intro_orig.md +0 -275
  71. md_processing/dr_egeria_inbox/archive/test-term.md +0 -110
  72. md_processing/dr_egeria_inbox/cat_test.md +0 -100
  73. md_processing/dr_egeria_inbox/collections.md +0 -39
  74. md_processing/dr_egeria_inbox/data_designer_debug.log +0 -6
  75. md_processing/dr_egeria_inbox/data_designer_out.md +0 -60
  76. md_processing/dr_egeria_inbox/data_designer_search_test.md +0 -11
  77. md_processing/dr_egeria_inbox/data_field.md +0 -54
  78. md_processing/dr_egeria_inbox/data_spec.md +0 -77
  79. md_processing/dr_egeria_inbox/data_spec_test.md +0 -2340
  80. md_processing/dr_egeria_inbox/data_test.md +0 -179
  81. md_processing/dr_egeria_inbox/data_test2.md +0 -429
  82. md_processing/dr_egeria_inbox/data_test3.md +0 -462
  83. md_processing/dr_egeria_inbox/dr_egeria_data_designer_1.md +0 -124
  84. md_processing/dr_egeria_inbox/dr_egeria_intro_categories.md +0 -168
  85. md_processing/dr_egeria_inbox/dr_egeria_intro_part1.md +0 -280
  86. md_processing/dr_egeria_inbox/dr_egeria_intro_part2.md +0 -318
  87. md_processing/dr_egeria_inbox/dr_egeria_intro_part3.md +0 -1073
  88. md_processing/dr_egeria_inbox/dr_egeria_isc1.md +0 -44
  89. md_processing/dr_egeria_inbox/generated_help_report.md +0 -9
  90. md_processing/dr_egeria_inbox/generated_help_terms.md +0 -842
  91. md_processing/dr_egeria_inbox/glossary_list.md +0 -5
  92. md_processing/dr_egeria_inbox/glossary_search_test.md +0 -40
  93. md_processing/dr_egeria_inbox/glossary_test1.md +0 -378
  94. md_processing/dr_egeria_inbox/gov_def.md +0 -718
  95. md_processing/dr_egeria_inbox/gov_def2.md +0 -447
  96. md_processing/dr_egeria_inbox/img.png +0 -0
  97. md_processing/dr_egeria_inbox/output_tests.md +0 -114
  98. md_processing/dr_egeria_inbox/product.md +0 -211
  99. md_processing/dr_egeria_inbox/rel.md +0 -8
  100. md_processing/dr_egeria_inbox/sb.md +0 -119
  101. md_processing/dr_egeria_inbox/solution-components.md +0 -136
  102. md_processing/dr_egeria_inbox/solution_blueprints.md +0 -118
  103. md_processing/dr_egeria_inbox/synonym_test.md +0 -42
  104. md_processing/dr_egeria_inbox/t2.md +0 -268
  105. md_processing/dr_egeria_outbox/.DS_Store +0 -0
  106. md_processing/dr_egeria_outbox/.obsidian/app.json +0 -1
  107. md_processing/dr_egeria_outbox/.obsidian/appearance.json +0 -1
  108. md_processing/dr_egeria_outbox/.obsidian/community-plugins.json +0 -7
  109. md_processing/dr_egeria_outbox/.obsidian/core-plugins.json +0 -33
  110. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/main.js +0 -5164
  111. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/manifest.json +0 -10
  112. md_processing/dr_egeria_outbox/.obsidian/plugins/buttons/styles.css +0 -624
  113. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/data.json +0 -10
  114. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/main.js +0 -4459
  115. md_processing/dr_egeria_outbox/.obsidian/plugins/calendar/manifest.json +0 -10
  116. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/data.json +0 -3
  117. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/main.js +0 -153
  118. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/manifest.json +0 -11
  119. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-kanban/styles.css +0 -1
  120. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/main.js +0 -500
  121. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/manifest.json +0 -12
  122. md_processing/dr_egeria_outbox/.obsidian/plugins/obsidian-tasks-plugin/styles.css +0 -1
  123. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/data.json +0 -38
  124. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/main.js +0 -37
  125. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/manifest.json +0 -11
  126. md_processing/dr_egeria_outbox/.obsidian/plugins/templater-obsidian/styles.css +0 -220
  127. md_processing/dr_egeria_outbox/.obsidian/types.json +0 -28
  128. md_processing/dr_egeria_outbox/.obsidian/workspace.json +0 -270
  129. md_processing/dr_egeria_outbox/Button Test.md +0 -11
  130. md_processing/dr_egeria_outbox/Scripts/.DS_Store +0 -0
  131. md_processing/dr_egeria_outbox/Scripts/sendRest.js +0 -24
  132. md_processing/dr_egeria_outbox/Templates/sendToApi.md.md +0 -17
  133. md_processing/dr_egeria_outbox/Untitled.canvas +0 -1
  134. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 09:26-product.md +0 -210
  135. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +0 -209
  136. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +0 -263
  137. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +0 -2374
  138. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +0 -2374
  139. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +0 -2321
  140. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +0 -2304
  141. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +0 -2324
  142. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +0 -2324
  143. md_processing/dr_egeria_outbox/processed-2025-08-30 16:56-generated_help_terms.md +0 -795
  144. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 15:00-Derive-Dr-Gov-Defs.md +0 -719
  145. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:13-Derive-Dr-Gov-Defs.md +0 -41
  146. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:14-Derive-Dr-Gov-Defs.md +0 -33
  147. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 20:50-Derive-Dr-Gov-Defs.md +0 -192
  148. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:08-gov_def2.md +0 -486
  149. md_processing/dr_egeria_outbox/thursday/processed-2025-07-17 22:10-gov_def2.md +0 -486
  150. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:53-gov_def2.md +0 -486
  151. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 08:54-gov_def2.md +0 -486
  152. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:03-gov_def2.md +0 -486
  153. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:06-gov_def2.md +0 -486
  154. md_processing/dr_egeria_outbox/thursday/processed-2025-07-18 09:10-gov_def2.md +0 -486
  155. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:07-gov_def.md +0 -492
  156. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:25-gov_def.md +0 -520
  157. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:43-gov_def.md +0 -636
  158. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:46-gov_def.md +0 -636
  159. md_processing/family_docs/Data Designer/Create_Data_Class.md +0 -164
  160. md_processing/family_docs/Data Designer/Create_Data_Dictionary.md +0 -30
  161. md_processing/family_docs/Data Designer/Create_Data_Field.md +0 -162
  162. md_processing/family_docs/Data Designer/Create_Data_Specification.md +0 -36
  163. md_processing/family_docs/Data Designer/Create_Data_Structure.md +0 -38
  164. md_processing/family_docs/Data Designer/View_Data_Classes.md +0 -78
  165. md_processing/family_docs/Data Designer/View_Data_Dictionaries.md +0 -78
  166. md_processing/family_docs/Data Designer/View_Data_Fields.md +0 -78
  167. md_processing/family_docs/Data Designer/View_Data_Specifications.md +0 -78
  168. md_processing/family_docs/Data Designer/View_Data_Structures.md +0 -78
  169. md_processing/family_docs/Data Designer.md +0 -842
  170. md_processing/family_docs/Digital Product Manager/Add_Member->Collection.md +0 -42
  171. md_processing/family_docs/Digital Product Manager/Attach_Collection->Resource.md +0 -36
  172. md_processing/family_docs/Digital Product Manager/Create_Agreement.md +0 -96
  173. md_processing/family_docs/Digital Product Manager/Create_Data_Sharing_Agreement.md +0 -72
  174. md_processing/family_docs/Digital Product Manager/Create_DigitalSubscription.md +0 -102
  175. md_processing/family_docs/Digital Product Manager/Create_Digital_Product.md +0 -134
  176. md_processing/family_docs/Digital Product Manager/Link_Agreement_Items.md +0 -60
  177. md_processing/family_docs/Digital Product Manager/Link_Contracts.md +0 -26
  178. md_processing/family_docs/Digital Product Manager/Link_Digital_Product_-_Digital_Product.md +0 -30
  179. md_processing/family_docs/Digital Product Manager/Link_Subscribers.md +0 -48
  180. md_processing/family_docs/Digital Product Manager.md +0 -668
  181. md_processing/family_docs/Glossary/Attach_Category_Parent.md +0 -18
  182. md_processing/family_docs/Glossary/Attach_Term-Term_Relationship.md +0 -26
  183. md_processing/family_docs/Glossary/Create_Category.md +0 -38
  184. md_processing/family_docs/Glossary/Create_Glossary.md +0 -42
  185. md_processing/family_docs/Glossary/Create_Term.md +0 -70
  186. md_processing/family_docs/Glossary.md +0 -206
  187. md_processing/family_docs/Governance Officer/Create_Business_Imperative.md +0 -106
  188. md_processing/family_docs/Governance Officer/Create_Certification_Type.md +0 -112
  189. md_processing/family_docs/Governance Officer/Create_Governance_Approach.md +0 -114
  190. md_processing/family_docs/Governance Officer/Create_Governance_Obligation.md +0 -114
  191. md_processing/family_docs/Governance Officer/Create_Governance_Principle.md +0 -114
  192. md_processing/family_docs/Governance Officer/Create_Governance_Procedure.md +0 -128
  193. md_processing/family_docs/Governance Officer/Create_Governance_Process.md +0 -122
  194. md_processing/family_docs/Governance Officer/Create_Governance_Processing_Purpose.md +0 -106
  195. md_processing/family_docs/Governance Officer/Create_Governance_Responsibility.md +0 -122
  196. md_processing/family_docs/Governance Officer/Create_Governance_Rule.md +0 -122
  197. md_processing/family_docs/Governance Officer/Create_Governance_Strategy.md +0 -106
  198. md_processing/family_docs/Governance Officer/Create_License_Type.md +0 -112
  199. md_processing/family_docs/Governance Officer/Create_Naming_Standard_Rule.md +0 -122
  200. md_processing/family_docs/Governance Officer/Create_Regulation_Article.md +0 -106
  201. md_processing/family_docs/Governance Officer/Create_Regulation_Definition.md +0 -118
  202. md_processing/family_docs/Governance Officer/Create_Security_Access_Control.md +0 -114
  203. md_processing/family_docs/Governance Officer/Create_Security_Group.md +0 -120
  204. md_processing/family_docs/Governance Officer/Create_Service_Level_Objectives.md +0 -122
  205. md_processing/family_docs/Governance Officer/Create_Threat_Definition.md +0 -106
  206. md_processing/family_docs/Governance Officer/Link_Governance_Controls.md +0 -32
  207. md_processing/family_docs/Governance Officer/Link_Governance_Drivers.md +0 -32
  208. md_processing/family_docs/Governance Officer/Link_Governance_Policies.md +0 -32
  209. md_processing/family_docs/Governance Officer/View_Governance_Definitions.md +0 -82
  210. md_processing/family_docs/Governance Officer.md +0 -2412
  211. md_processing/family_docs/Solution Architect/Create_Information_Supply_Chain.md +0 -70
  212. md_processing/family_docs/Solution Architect/Create_Solution_Blueprint.md +0 -44
  213. md_processing/family_docs/Solution Architect/Create_Solution_Component.md +0 -96
  214. md_processing/family_docs/Solution Architect/Create_Solution_Role.md +0 -66
  215. md_processing/family_docs/Solution Architect/Link_Information_Supply_Chain_Peers.md +0 -32
  216. md_processing/family_docs/Solution Architect/Link_Solution_Component_Peers.md +0 -32
  217. md_processing/family_docs/Solution Architect/View_Information_Supply_Chains.md +0 -32
  218. md_processing/family_docs/Solution Architect/View_Solution_Blueprints.md +0 -32
  219. md_processing/family_docs/Solution Architect/View_Solution_Components.md +0 -32
  220. md_processing/family_docs/Solution Architect/View_Solution_Roles.md +0 -32
  221. md_processing/family_docs/Solution Architect.md +0 -490
  222. md_processing/md_commands/old_project_commands.py +0 -164
  223. md_processing/md_processing_utils/debug_log.log +0 -5580
  224. md_processing/md_processing_utils/generated_help_terms.md +0 -842
  225. md_processing/md_processing_utils/logs/pyegeria.log +0 -56
  226. pyegeria/.DS_Store +0 -0
  227. pyegeria/___external_references.py +0 -3267
  228. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/LICENSE +0 -0
  229. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/WHEEL +0 -0
  230. {pyegeria-5.4.3.3.dist-info → pyegeria-5.4.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1794 @@
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._globals import NO_GUID_RETURNED
16
+ from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
17
+ from pyegeria.config import settings
18
+ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
19
+ TemplateRequestBody,
20
+ UpdateElementRequestBody, UpdateStatusRequestBody, NewRelationshipRequestBody,
21
+ DeleteRequestBody, UpdateRelationshipRequestBody, get_defined_field_values)
22
+ from pyegeria.output_formatter import (generate_output,
23
+ _extract_referenceable_properties, populate_columns_from_properties,
24
+ get_required_relationships)
25
+ from pyegeria.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","ExternalModelSourceProperties",
30
+ "RelatedMediaProperties","CitedDocumentProperties"]
31
+
32
+ EXTERNAL_REFERENCE_TYPES = ["ExternalReference","ExternalDataSource","ExternalModelSource",
33
+ "RelatedMedia","CitedDocument"]
34
+ from pyegeria._client_new import Client2
35
+
36
+
37
+ class ExternalReferences(Client2):
38
+ """
39
+ Establish linkage to external references which can be a variety of artifacts. Including media,
40
+ documents, data, and more. Keep in mind that there are several sub-types of external references, each
41
+ with their own property body. This includes:
42
+
43
+ * ExternalReferenceProperties
44
+ * ExternalDataSourceProperties
45
+ * ExternalModelSourceProperties
46
+ * RelatedMediaProperties
47
+ * CitedDocumentProperties
48
+
49
+ Review the documentation on the website for more details.
50
+
51
+ Attributes:
52
+
53
+ server_name: str
54
+ The name of the View Server to connect to.
55
+ platform_url : str
56
+ URL of the server platform to connect to
57
+ user_id : str
58
+ The identity of the user calling the method - this sets a default optionally used by the methods
59
+ when the user doesn't pass the user_id on a method call.
60
+ user_pwd: str
61
+ The password associated with the user_id. Defaults to None
62
+ token: str
63
+ An optional bearer token
64
+
65
+ """
66
+
67
+ def __init__(self, view_server: str, platform_url: str, user_id: str, user_pwd: str = None, token: str = None, ):
68
+ self.view_server = view_server
69
+ self.platform_url = platform_url
70
+ self.user_id = user_id
71
+ self.user_pwd = user_pwd
72
+
73
+ Client2.__init__(self, view_server, platform_url, user_id, user_pwd, token)
74
+ result = self.get_platform_origin()
75
+ logger.info(f"ExternalReferences initialized, platform origin is: {result}")
76
+ self.command_root: str = (
77
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external-references")
78
+
79
+ @dynamic_catch
80
+ async def _async_create_external_reference(self, body: dict | NewElementRequestBody = None) -> str:
81
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
82
+ and classification will be used to create a simple, self-anchored external_reference.
83
+ Collections: https://egeria-project.org/concepts/external_reference
84
+ Async version.
85
+
86
+ Parameters
87
+ ----------
88
+
89
+
90
+ body: dict | NewElementRequestBody, optional
91
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
92
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
93
+ validated before being used.
94
+
95
+ Returns
96
+ -------
97
+ str - the guid of the created external_reference
98
+
99
+ Raises
100
+ ------
101
+ PyegeriaException
102
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
103
+ Egeria errors.
104
+ ValidationError
105
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
106
+ NotAuthorizedException
107
+ The principle specified by the user_id does not have authorization for the requested action
108
+
109
+ Notes:
110
+ -----
111
+ simple:
112
+ {
113
+ "class": "NewElementRequestBody",
114
+ "isOwnAnchor": true,
115
+ "properties": {
116
+ "class": "ExternalReferenceProperties",
117
+ "qualifiedName": "Must provide a unique name here",
118
+ "name": "Add display name here",
119
+ "description": "Add description of the external_reference here",
120
+ "category": "Add appropriate valid value for type",
121
+ "referenceTitle: "Add reference title here",
122
+ "referenceAbstract": "Add reference abstract here",
123
+ "authors": ["Add author names here"],
124
+ "url": "Add url here",
125
+ "datePublished": "2023-01-01",
126
+ "dateConnected": "2023-01-01",
127
+ "dateCreated": "2023-01-01",
128
+ }
129
+ }
130
+
131
+ For related media use this properties body:
132
+ {
133
+ "class": "NewElementRequestBody",
134
+ "isOwnAnchor": true,
135
+ "properties": {
136
+ "class": "RelatedMediaProperties",
137
+ "qualifiedName": "Must provide a unique name here",
138
+ "name": "Add display name here",
139
+ "description": "Add description of the external_reference here",
140
+ "category": "Add appropriate valid value for type",
141
+ "referenceTitle: "Add reference title here",
142
+ "referenceAbstract": "Add reference abstract here",
143
+ "authors": ["Add author names here"],
144
+ "url": "Add url here",
145
+ "datePublished": "2023-01-01",
146
+ "dateConnected": "2023-01-01",
147
+ "dateCreated": "2023-01-01",
148
+ "mediaType": "Add media type here",
149
+ "mediaTypeOtherId": "Add media type other id here",
150
+ "defaultMediaUsage": "Add default media usage here",
151
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
152
+ }
153
+ }
154
+
155
+ See https://egeria-project.org/types/0/0015-Linked-Media-Types/ for more information on media types and
156
+ valid values.
157
+
158
+ """
159
+
160
+ url = f"{self.command_root}/external-references"
161
+ return await self._async_create_element_body_request(url,EXTERNAL_REFERENCE_PROPS,body)
162
+
163
+ @dynamic_catch
164
+ def create_external_reference(self, body: dict | NewElementRequestBody = None) -> str:
165
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
166
+ and classification will be used to create a simple, self-anchored external_reference.
167
+ Collections: https://egeria-project.org/concepts/external_reference
168
+ Async version.
169
+
170
+ Parameters
171
+ ----------
172
+
173
+
174
+ body: dict | NewElementRequestBody, optional
175
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
176
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
177
+ validated before being used.
178
+
179
+ Returns
180
+ -------
181
+ str - the guid of the created external_reference
182
+
183
+ Raises
184
+ ------
185
+ PyegeriaException
186
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
187
+ Egeria errors.
188
+ ValidationError
189
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
190
+ NotAuthorizedException
191
+ The principle specified by the user_id does not have authorization for the requested action
192
+
193
+ Notes:
194
+ -----
195
+ simple:
196
+ {
197
+ "class": "NewElementRequestBody",
198
+ "isOwnAnchor": true,
199
+ "properties": {
200
+ "class": "ExternalReferenceProperties",
201
+ "qualifiedName": "Must provide a unique name here",
202
+ "name": "Add display name here",
203
+ "description": "Add description of the external_reference here",
204
+ "category": "Add appropriate valid value for type",
205
+ "referenceTitle": "Add reference title here",
206
+ "referenceAbstract": "Add reference abstract here",
207
+ "authors": ["Add author names here"],
208
+ "url": "Add url here",
209
+ "sources": "Add sources here",
210
+ "license": "Add license here",
211
+ "copyright": "Add copyright here",
212
+ "attribution": "Add attribution here"
213
+ }
214
+ }
215
+
216
+ For related media use this properties body:
217
+ {
218
+ "class": "NewElementRequestBody",
219
+ "isOwnAnchor": true,
220
+ "properties": {
221
+ "class": "RelatedMediaProperties",
222
+ "qualifiedName": "Must provide a unique name here",
223
+ "name": "Add display name here",
224
+ "description": "Add description of the external_reference here",
225
+ "category": "Add appropriate valid value for type",
226
+ "referenceTitle": "Add reference title here",
227
+ "referenceAbstract": "Add reference abstract here",
228
+ "authors": ["Add author names here"],
229
+ "url": "Add url here",
230
+ "sources": "Add sources here",
231
+ "license": "Add license here",
232
+ "copyright": "Add copyright here",
233
+ "attribution": "Add attribution here",
234
+ "datePublished": "2023-01-01",
235
+ "dateConnected": "2023-01-01",
236
+ "dateCreated": "2023-01-01",
237
+ "mediaType": "Add media type here",
238
+ "mediaTypeOtherId": "Add media type other id here",
239
+ "defaultMediaUsage": "Add default media usage here",
240
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
241
+ }
242
+ }
243
+
244
+ For CitedDocument use this properties body:
245
+ {
246
+ "class": "NewElementRequestBody",
247
+ "isOwnAnchor": true,
248
+ "properties": {
249
+ "class": "CitedDocumentProperties",
250
+ "qualifiedName": "Must provide a unique name here",
251
+ "name": "Add display name here",
252
+ "description": "Add description of the external_reference here",
253
+ "category": "Add appropriate valid value for type",
254
+ "numberOfPates": int,
255
+ "pageRange": "Add page range here",
256
+ "publicationSeries": "Add publication series here",
257
+ "publicationSeriesVolume": "Add publication series volume here",
258
+ "publisher": "Add publisher here",
259
+ "edition": "Add edition here",
260
+ "firstPublicationDate": "2023-01-01",
261
+ "publicationDate": "2023-01-01",
262
+ "publicationCity": "Add publication city here",
263
+ "publicationYear": "publication year",
264
+ "publicationNumbers": ["string"],
265
+ "defaultMediaUsage": "Add default media usage here",
266
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
267
+ "referenceTitle": "Add reference title here",
268
+ "referenceAbstract": "Add reference abstract here",
269
+ "authors": ["Add author names here"],
270
+ "url": "Add url here",
271
+ "sources": "Add sources here",
272
+ "license": "Add license here",
273
+ "copyright": "Add copyright here",
274
+ "attribution": "Add attribution here"
275
+ }
276
+ }
277
+
278
+ See https://egeria-project.org/types/0/0015-Linked-Media-Types/ for more information on media types and
279
+ valid values.
280
+
281
+
282
+ """
283
+
284
+ return asyncio.get_event_loop().run_until_complete(self._async_create_external_reference(body))
285
+
286
+
287
+ #######
288
+
289
+ @dynamic_catch
290
+ async def _async_create_external_reference_from_template(self, body: TemplateRequestBody | dict) -> 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
+ InvalidParameterException
308
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
309
+ PropertyServerException
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}/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: dict) -> 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
+ InvalidParameterException
375
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
376
+ PropertyServerException
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
+
419
+ @dynamic_catch
420
+ async def _async_update_external_reference(self, external_reference_guid: str,
421
+ body: dict | UpdateElementRequestBody) -> None:
422
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
423
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
424
+ Collections: https://egeria-project.org/concepts/external_reference
425
+
426
+ Async version.
427
+ Parameters
428
+ ----------
429
+ external_reference_guid: str
430
+ The guid of the external_reference to update.
431
+
432
+ body: dict | UpdateElementRequestBody, optional
433
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
434
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
435
+ validated before being used.
436
+ merge_update: bool, optional, default = True
437
+ If true then property changes will be overlaid on top of existing properties. If false, existing
438
+ properties will all be replaced by the set provided in the update request.
439
+
440
+ Returns
441
+ -------
442
+ None
443
+
444
+ Raises
445
+ ------
446
+ PyegeriaException
447
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
448
+ Egeria errors.
449
+ ValidationError
450
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
451
+ NotAuthorizedException
452
+ The principle specified by the user_id does not have authorization for the requested action
453
+
454
+ Notes:
455
+ -----
456
+ simple example:
457
+ {
458
+ "class" : "UpdateElementRequestBody",
459
+ "properties": {
460
+ "class" : "CollectionProperties",
461
+ "qualifiedName": "Must provide a unique name here",
462
+ "name" : "Add display name here",
463
+ "description" : "Add description of the external_reference here",
464
+ "category": "Add appropriate valid value for type"
465
+ },
466
+ "externalSourceGUID": "add guid here",
467
+ "externalSourceName": "add qualified name here",
468
+ "effectiveTime" : "{{$isoTimestamp}}",
469
+ "forLineage" : false,
470
+ "forDuplicateProcessing" : false
471
+ }
472
+ """
473
+
474
+ # try:
475
+
476
+ url = (f"{self.command_root}/{external_reference_guid}/update")
477
+ await self._async_update_element_body_request(url, EXTERNAL_REFERENCE_PROPS, body)
478
+
479
+
480
+ @dynamic_catch
481
+ def update_external_reference(self, external_reference_guid: str, body: dict | NewElementRequestBody) -> None:
482
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
483
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
484
+ Collections: https://egeria-project.org/concepts/external_reference
485
+
486
+ Parameters
487
+ ----------
488
+ external_reference_guid: str
489
+ The guid of the external_reference to update.
490
+
491
+ body: dict | NewElementRequestBody, optional
492
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
493
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
494
+ validated before being used.
495
+ merge_update: bool, optional, default = True
496
+ If true then property changes will be overlaid on top of existing properties. If false, existing
497
+ properties will all be replaced by the set provided in the update request.
498
+
499
+ Returns
500
+ -------
501
+ None
502
+
503
+ Raises
504
+ ------
505
+ PyegeriaException
506
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
507
+ Egeria errors.
508
+ ValidationError
509
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
510
+ NotAuthorizedException
511
+ The principle specified by the user_id does not have authorization for the requested action
512
+
513
+ Notes:
514
+ -----
515
+ simple example:
516
+ {
517
+ "class" : "UpdateElementRequestBody",
518
+ "properties": {
519
+ "class" : "CollectionProperties",
520
+ "qualifiedName": "Must provide a unique name here",
521
+ "name" : "Add display name here",
522
+ "description" : "Add description of the external_reference here",
523
+ "category": "Add appropriate valid value for type"
524
+ },
525
+ "externalSourceGUID": "add guid here",
526
+ "externalSourceName": "add qualified name here",
527
+ "effectiveTime" : "{{$isoTimestamp}}",
528
+ "forLineage" : false,
529
+ "forDuplicateProcessing" : false
530
+ }
531
+ """
532
+
533
+ return asyncio.get_event_loop().run_until_complete(
534
+ self._async_update_external_reference(external_reference_guid, body))
535
+
536
+ @dynamic_catch
537
+ async def _async_link_external_reference(self, element_guid: str, ext_ref_guid: str,
538
+ body: dict | NewRelationshipRequestBody = None) -> None:
539
+ """ Attach an element to an external reference.
540
+ Async version.
541
+
542
+ Parameters
543
+ ----------
544
+ element_guid: str
545
+ The unique identifier of the element.
546
+ ext_ref_guid: str
547
+ The identifier of the external reference.
548
+ body: dict | NewRelationshipRequestBody, optional, default = None
549
+ A structure representing the details of the relationship.
550
+
551
+ Returns
552
+ -------
553
+ Nothing
554
+
555
+ Raises
556
+ ------
557
+ InvalidParameterException
558
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
559
+ PropertyServerException
560
+ Raised by the server when an issue arises in processing a valid request
561
+ NotAuthorizedException
562
+ The principle specified by the user_id does not have authorization for the requested action
563
+
564
+ Notes
565
+ -----
566
+ JSON Structure looks like:
567
+ {
568
+ "class" : "NewRelationshipRequestBody",
569
+ "externalSourceGUID": "add guid here",
570
+ "externalSourceName": "add qualified name here",
571
+ "effectiveTime" : "{{$isoTimestamp}}",
572
+ "forLineage" : false,
573
+ "forDuplicateProcessing" : false,
574
+ "properties": {
575
+ "class": "ExternalReferenceLinkProperties",",
576
+ "label": "add label here",
577
+ "description": "add description here",
578
+ "effectiveFrom": "{{$isoTimestamp}}",
579
+ "effectiveTo": "{{$isoTimestamp}}"
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
+
588
+ @dynamic_catch
589
+ def link_external_reference(self, element_guid: str, ext_ref_guid: str,
590
+ body: dict | NewRelationshipRequestBody = None):
591
+ """ Attach an element to an external reference.
592
+
593
+ Parameters
594
+ ----------
595
+ element_guid: str
596
+ The unique identifier of the element.
597
+ ext_ref_guid: str
598
+ The identifier of the external reference.
599
+ body: dict | NewRelationshipRequestBody, optional, default = None
600
+ A structure representing the details of the relationship.
601
+
602
+ Returns
603
+ -------
604
+ Nothing
605
+
606
+ Raises
607
+ ------
608
+ InvalidParameterException
609
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
610
+ PropertyServerException
611
+ Raised by the server when an issue arises in processing a valid request
612
+ NotAuthorizedException
613
+ The principle specified by the user_id does not have authorization for the requested action
614
+
615
+ Notes
616
+ -----
617
+ JSON Structure looks like:
618
+ {
619
+ "class" : "NewRelationshipRequestBody",
620
+ "externalSourceGUID": "add guid here",
621
+ "externalSourceName": "add qualified name here",
622
+ "effectiveTime" : "{{$isoTimestamp}}",
623
+ "forLineage" : false,
624
+ "forDuplicateProcessing" : false,
625
+ "properties": {
626
+ "class": "ExternalReferenceLinkProperties",",
627
+ "label": "add label here",
628
+ "description": "add description here",
629
+ "effectiveFrom": "{{$isoTimestamp}}",
630
+ "effectiveTo": "{{$isoTimestamp}}"
631
+ }
632
+ }
633
+ """
634
+ loop = asyncio.get_event_loop()
635
+ loop.run_until_complete(self._async_link_external_reference(element_guid, ext_ref_guid, body))
636
+
637
+
638
+ @dynamic_catch
639
+ async def _async_detach_external_reference(self, element_guid: str, ext_ref_guid: str,
640
+ body: dict | DeleteRequestBody = None) -> None:
641
+ """ Detach an element from an external reference; body is optional. Async version.
642
+
643
+ Parameters
644
+ ----------
645
+ element_guid: str
646
+ The unique identifier of the subscriber.
647
+ ext_ref_guid: str
648
+ The unique identifier of the subscription.
649
+ body: dict | DeleteRequestBody, optional, default = None
650
+ A structure representing the details of the relationship.
651
+
652
+ Returns
653
+ -------
654
+ Nothing
655
+
656
+ Raises
657
+ ------
658
+ InvalidParameterException
659
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
660
+ PropertyServerException
661
+ Raised by the server when an issue arises in processing a valid request
662
+ NotAuthorizedException
663
+ The principle specified by the user_id does not have authorization for the requested action
664
+
665
+ Notes
666
+ -----
667
+ JSON Structure looks like:
668
+ {
669
+ "class": "DeleteRequestBody",
670
+ "externalSourceGUID": "add guid here",
671
+ "externalSourceName": "add qualified name here",
672
+ "effectiveTime": "{{$isoTimestamp}}",
673
+ "forLineage": false,
674
+ "forDuplicateProcessing": false
675
+ }
676
+ """
677
+ url = (f"{self.command_root}/elements/{element_guid}/external_references/{ext_ref_guid}/detach")
678
+
679
+ await self._async_delete_request(url, body)
680
+ logger.info(f"Detached element {element_guid} from external reference {ext_ref_guid}")
681
+
682
+
683
+ def detach_external_reference(self, element_guid: str, ext_ref_guid: str, body: dict | DeleteRequestBody = None):
684
+ """ Detach an element from an external reference. Request body is optional.
685
+
686
+ Parameters
687
+ ----------
688
+ element_guid: str
689
+ The unique identifier of the subscriber.
690
+ ext_ref_guid: str
691
+ The unique identifier of the subscription.
692
+ body: dict, optional, default = None
693
+ A dict representing the details of the relationship.
694
+
695
+ Returns
696
+ -------
697
+ Nothing
698
+
699
+ Raises
700
+ ------
701
+ InvalidParameterException
702
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
703
+ PropertyServerException
704
+ Raised by the server when an issue arises in processing a valid request
705
+ NotAuthorizedException
706
+ The principle specified by the user_id does not have authorization for the requested action
707
+
708
+ Notes
709
+ -----
710
+ JSON Structure looks like:
711
+ {
712
+ "class": "DeleteRequestBody",
713
+ "externalSourceGUID": "add guid here",
714
+ "externalSourceName": "add qualified name here",
715
+ "effectiveTime": "{{$isoTimestamp}}",
716
+ "forLineage": false,
717
+ "forDuplicateProcessing": false
718
+ }
719
+ """
720
+ loop = asyncio.get_event_loop()
721
+ loop.run_until_complete(self._async_detach_external_reference(element_guid, ext_ref_guid, body))
722
+
723
+
724
+ @dynamic_catch
725
+ async def _async_link_media_reference(self, element_guid: str, media_ref_guid: str,
726
+ body: dict | NewRelationshipRequestBody = None) -> None:
727
+ """ Attach an element to a related media reference.
728
+ Async version.
729
+
730
+ Parameters
731
+ ----------
732
+ element_guid: str
733
+ The unique identifier of the element.
734
+ media_ref_guid: str
735
+ The identifier of the external media reference.
736
+ body: dict | NewRelationshipRequestBody, optional, default = None
737
+ A structure representing the details of the relationship.
738
+
739
+ Returns
740
+ -------
741
+ Nothing
742
+
743
+ Raises
744
+ ------
745
+ InvalidParameterException
746
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
747
+ PropertyServerException
748
+ Raised by the server when an issue arises in processing a valid request
749
+ NotAuthorizedException
750
+ The principle specified by the user_id does not have authorization for the requested action
751
+
752
+ Notes
753
+ -----
754
+ JSON Structure looks like:
755
+ {
756
+ "class" : "NewRelationshipRequestBody",
757
+ "externalSourceGUID": "add guid here",
758
+ "externalSourceName": "add qualified name here",
759
+ "effectiveTime" : "{{$isoTimestamp}}",
760
+ "forLineage" : false,
761
+ "forDuplicateProcessing" : false,
762
+ "properties": {
763
+ "class": "CitedDocumentProperties",
764
+ "qualifiedName": "Must provide a unique name here",
765
+ "name": "Add display name here",
766
+ "description": "Add description of the external_reference here",
767
+ "category": "Add appropriate valid value for type",
768
+ "numberOfPates": int,
769
+ "pageRange": "Add page range here",
770
+ "publicationSeries": "Add publication series here",
771
+ "publicationSeriesVolume": "Add publication series volume here",
772
+ "publisher": "Add publisher here",
773
+ "edition": "Add edition here",
774
+ "firstPublicationDate": "2023-01-01",
775
+ "publicationDate": "2023-01-01",
776
+ "publicationCity": "Add publication city here",
777
+ "publicationYear": "publication year",
778
+ "publicationNumbers": ["string"],
779
+ "defaultMediaUsage": "Add default media usage here",
780
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
781
+ "referenceTitle": "Add reference title here",
782
+ "referenceAbstract": "Add reference abstract here",
783
+ "authors": ["Add author names here"],
784
+ "url": "Add url here",
785
+ "sources": "Add sources here",
786
+ "license": "Add license here",
787
+ "copyright": "Add copyright here",
788
+ "attribution": "Add attribution here"
789
+ }
790
+ }
791
+ """
792
+ url =f"{self.command_root}/elements/{element_guid}/media-references/{media_ref_guid}/attach"
793
+ await self._async_new_relationship_request(url, "MediaReferenceProperties", body)
794
+ logger.info(f"Linking element {element_guid} to media reference {media_ref_guid}")
795
+
796
+
797
+
798
+
799
+ @dynamic_catch
800
+ def link_media_reference(self, element_guid: str, media_ref_guid: str,
801
+ body: dict | NewRelationshipRequestBody = None):
802
+ """ Attach an element to an external media reference.
803
+
804
+ Parameters
805
+ ----------
806
+ element_guid: str
807
+ The unique identifier of the element.
808
+ media_ref_guid: str
809
+ The identifier of the external reference.
810
+ body: dict | NewRelationshipRequestBody, optional, default = None
811
+ A structure representing the details of the relationship.
812
+
813
+ Returns
814
+ -------
815
+ Nothing
816
+
817
+ Raises
818
+ ------
819
+ InvalidParameterException
820
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
821
+ PropertyServerException
822
+ Raised by the server when an issue arises in processing a valid request
823
+ NotAuthorizedException
824
+ The principle specified by the user_id does not have authorization for the requested action
825
+
826
+ Notes
827
+ -----
828
+ JSON Structure looks like:
829
+ {
830
+ "class" : "NewRelationshipRequestBody",
831
+ "externalSourceGUID": "add guid here",
832
+ "externalSourceName": "add qualified name here",
833
+ "effectiveTime" : "{{$isoTimestamp}}",
834
+ "forLineage" : false,
835
+ "forDuplicateProcessing" : false,
836
+ "properties": {
837
+ "class": "CitedDocumentProperties",
838
+ "qualifiedName": "Must provide a unique name here",
839
+ "name": "Add display name here",
840
+ "description": "Add description of the external_reference here",
841
+ "category": "Add appropriate valid value for type",
842
+ "numberOfPates": int,
843
+ "pageRange": "Add page range here",
844
+ "publicationSeries": "Add publication series here",
845
+ "publicationSeriesVolume": "Add publication series volume here",
846
+ "publisher": "Add publisher here",
847
+ "edition": "Add edition here",
848
+ "firstPublicationDate": "2023-01-01",
849
+ "publicationDate": "2023-01-01",
850
+ "publicationCity": "Add publication city here",
851
+ "publicationYear": "publication year",
852
+ "publicationNumbers": ["string"],
853
+ "defaultMediaUsage": "Add default media usage here",
854
+ "defaultMediaUsageOtherId": "Add default media usage other id here",
855
+ "referenceTitle": "Add reference title here",
856
+ "referenceAbstract": "Add reference abstract here",
857
+ "authors": ["Add author names here"],
858
+ "url": "Add url here",
859
+ "sources": "Add sources here",
860
+ "license": "Add license here",
861
+ "copyright": "Add copyright here",
862
+ "attribution": "Add attribution here"
863
+ }
864
+ }
865
+ """
866
+ loop = asyncio.get_event_loop()
867
+ loop.run_until_complete(self._async_link_media_reference(element_guid, media_ref_guid, body))
868
+
869
+ @dynamic_catch
870
+ async def _async_detach_media_reference(self, element_guid: str, media_ref_guid: str,
871
+ body: dict | DeleteRequestBody = None) -> None:
872
+ """ Detach an element from an external media reference; body is optional. Async version.
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 | DeleteRequestBody, optional, default = None
881
+ A structure representing the details of the relationship.
882
+
883
+ Returns
884
+ -------
885
+ Nothing
886
+
887
+ Raises
888
+ ------
889
+ InvalidParameterException
890
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
891
+ PropertyServerException
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": "DeleteRequestBody",
901
+ "externalSourceGUID": "add guid here",
902
+ "externalSourceName": "add qualified name here",
903
+ "effectiveTime": "{{$isoTimestamp}}",
904
+ "forLineage": false,
905
+ "forDuplicateProcessing": false
906
+ }
907
+ """
908
+ url = (
909
+ f"{self.command_root}/elements/{element_guid}/media-references/{media_ref_guid}/detach")
910
+
911
+ await self._async_delete_request(url, body)
912
+ logger.info(f"Detached element {element_guid} from external media reference {media_ref_guid}")
913
+ @dynamic_catch
914
+ def detach_media_reference(self, element_guid: str, media_ref_guid: str, body: dict | DeleteRequestBody = None):
915
+ """ Detach an element from an external media reference. Request body is optional.
916
+
917
+ Parameters
918
+ ----------
919
+ element_guid: str
920
+ The unique identifier of the subscriber.
921
+ media_ref_guid: str
922
+ The unique identifier of the subscription.
923
+ body: dict, optional, default = None
924
+ A dict representing the details of the relationship.
925
+
926
+ Returns
927
+ -------
928
+ Nothing
929
+
930
+ Raises
931
+ ------
932
+ InvalidParameterException
933
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
934
+ PropertyServerException
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": "DeleteRequestBody",
944
+ "externalSourceGUID": "add guid here",
945
+ "externalSourceName": "add qualified name here",
946
+ "effectiveTime": "{{$isoTimestamp}}",
947
+ "forLineage": false,
948
+ "forDuplicateProcessing": false
949
+ }
950
+ """
951
+ loop = asyncio.get_event_loop()
952
+ loop.run_until_complete(self._async_detach_media_reference(element_guid, media_ref_guid, body))
953
+
954
+ @dynamic_catch
955
+ async def _async_link_cited_document(self, element_guid: str, cited_doc_guid: str,
956
+ body: dict | NewRelationshipRequestBody = None) -> None:
957
+ """ Attach an element to a cited document reference.
958
+ Async version.
959
+
960
+ Parameters
961
+ ----------
962
+ element_guid: str
963
+ The unique identifier of the element.
964
+ cited_doc_guid: str
965
+ The identifier of the external cited document reference.
966
+ body: dict | NewRelationshipRequestBody, optional, default = None
967
+ A structure representing the details of the relationship.
968
+
969
+ Returns
970
+ -------
971
+ Nothing
972
+
973
+ Raises
974
+ ------
975
+ InvalidParameterException
976
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
977
+ PropertyServerException
978
+ Raised by the server when an issue arises in processing a valid request
979
+ NotAuthorizedException
980
+ The principle specified by the user_id does not have authorization for the requested action
981
+
982
+ Notes
983
+ -----
984
+ JSON Structure looks like:
985
+ {
986
+ "class" : "NewRelationshipRequestBody",
987
+ "externalSourceGUID": "add guid here",
988
+ "externalSourceName": "add qualified name here",
989
+ "effectiveTime" : "{{$isoTimestamp}}",
990
+ "forLineage" : false,
991
+ "forDuplicateProcessing" : false,
992
+ "properties": {
993
+ "class": "CitedDocumentLinkProperties",
994
+ "referenceId": "add reference id here",
995
+ "description": "Add description of the external_reference here",
996
+ "pages": "Add pages here"
997
+ }
998
+ }
999
+ """
1000
+ url = f"{self.command_root}/elements/{element_guid}/cited-document-references/{cited_doc_guid}/attach"
1001
+ await self._async_new_relationship_request(url, "CitedDocumentLinkProperties", body)
1002
+ logger.info(f"Linking element {element_guid} to cited document {cited_doc_guid}")
1003
+
1004
+ @dynamic_catch
1005
+ def link_cited_document(self, element_guid: str, cited_doc_guid: str,
1006
+ body: dict | NewRelationshipRequestBody = None):
1007
+ """ Attach an element to an external media reference.
1008
+
1009
+ Parameters
1010
+ ----------
1011
+ element_guid: str
1012
+ The unique identifier of the element.
1013
+ cited_doc_guid: str
1014
+ The identifier of the external reference.
1015
+ body: dict | NewRelationshipRequestBody, optional, default = None
1016
+ A structure representing the details of the relationship.
1017
+
1018
+ Returns
1019
+ -------
1020
+ Nothing
1021
+
1022
+ Raises
1023
+ ------
1024
+ InvalidParameterException
1025
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1026
+ PropertyServerException
1027
+ Raised by the server when an issue arises in processing a valid request
1028
+ NotAuthorizedException
1029
+ The principle specified by the user_id does not have authorization for the requested action
1030
+
1031
+ Notes
1032
+ -----
1033
+ JSON Structure looks like:
1034
+ {
1035
+ "class" : "NewRelationshipRequestBody",
1036
+ "externalSourceGUID": "add guid here",
1037
+ "externalSourceName": "add qualified name here",
1038
+ "effectiveTime" : "{{$isoTimestamp}}",
1039
+ "forLineage" : false,
1040
+ "forDuplicateProcessing" : false,
1041
+ "properties": {
1042
+ "class": "CitedDocumentLinkProperties",
1043
+ "referenceId": "add reference id here",
1044
+ "description": "Add description of the external_reference here",
1045
+ "pages": "Add pages here"
1046
+ }
1047
+ }
1048
+ """
1049
+ loop = asyncio.get_event_loop()
1050
+ loop.run_until_complete(self._async_link_cited_document(element_guid, cited_doc_guid, body))
1051
+
1052
+ @dynamic_catch
1053
+ async def _async_detach_cited_document(self, element_guid: str, cited_doc_guid: str,
1054
+ body: dict | DeleteRequestBody = None) -> None:
1055
+ """ Detach an element from an cited document reference; body is optional. Async version.
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 | DeleteRequestBody, optional, default = None
1064
+ A structure representing the details of the relationship.
1065
+
1066
+ Returns
1067
+ -------
1068
+ Nothing
1069
+
1070
+ Raises
1071
+ ------
1072
+ InvalidParameterException
1073
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1074
+ PropertyServerException
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": "DeleteRequestBody",
1084
+ "externalSourceGUID": "add guid here",
1085
+ "externalSourceName": "add qualified name here",
1086
+ "effectiveTime": "{{$isoTimestamp}}",
1087
+ "forLineage": false,
1088
+ "forDuplicateProcessing": false
1089
+ }
1090
+ """
1091
+ url = f"{self.command_root}/elements/{element_guid}/cited-document-references/{cited_doc_guid}/detach"
1092
+
1093
+ await self._async_delete_request(url, body)
1094
+ logger.info(f"Detached element {element_guid} from cited document reference {cited_doc_guid}")
1095
+
1096
+ @dynamic_catch
1097
+ def detach_cited_document(self, element_guid: str, cited_doc_guid: str, body: dict | DeleteRequestBody = None):
1098
+ """ Detach an element from acited document reference. Request body is optional.
1099
+
1100
+ Parameters
1101
+ ----------
1102
+ element_guid: str
1103
+ The unique identifier of the subscriber.
1104
+ cited_doc_guid: str
1105
+ The unique identifier of the subscription.
1106
+ body: dict, optional, default = None
1107
+ A dict representing the details of the relationship.
1108
+
1109
+ Returns
1110
+ -------
1111
+ Nothing
1112
+
1113
+ Raises
1114
+ ------
1115
+ InvalidParameterException
1116
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1117
+ PropertyServerException
1118
+ Raised by the server when an issue arises in processing a valid request
1119
+ NotAuthorizedException
1120
+ The principle specified by the user_id does not have authorization for the requested action
1121
+
1122
+ Notes
1123
+ -----
1124
+ JSON Structure looks like:
1125
+ {
1126
+ "class": "DeleteRequestBody",
1127
+ "externalSourceGUID": "add guid here",
1128
+ "externalSourceName": "add qualified name here",
1129
+ "effectiveTime": "{{$isoTimestamp}}",
1130
+ "forLineage": false,
1131
+ "forDuplicateProcessing": false
1132
+ }
1133
+ """
1134
+ loop = asyncio.get_event_loop()
1135
+ loop.run_until_complete(self._async_detach_cited_document(element_guid, cited_doc_guid, body))
1136
+
1137
+ #
1138
+ # do deletes etc
1139
+ #
1140
+ @dynamic_catch
1141
+ async def _async_delete_external_reference(self, ext_ref_guid: str,
1142
+ body: dict | DeleteRequestBody = None,
1143
+ cascade: bool = False) -> None:
1144
+ """ Delete an external reference. Async Version.
1145
+
1146
+ Parameters
1147
+ ----------
1148
+ ext_ref_guid: str
1149
+ The guid of the governance definition to delete.
1150
+
1151
+ cascade: bool, optional, defaults to True
1152
+ If true, a cascade delete is performed.
1153
+
1154
+ body: dict DeleteRequestBodyt, optional, default = None
1155
+ A dict representing the details of the relationship.
1156
+
1157
+ Returns
1158
+ -------
1159
+ Nothing
1160
+
1161
+ Raises
1162
+ ------
1163
+ PyegeriaInvalidParameterException
1164
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1165
+ ValidationException
1166
+ Raised by pydantic when the request body is invalid.
1167
+ NotAuthorizedException
1168
+ The principle specified by the user_id does not have authorization for the requested action
1169
+
1170
+ Notes
1171
+ _____
1172
+ JSON Structure looks like:
1173
+ {
1174
+ "class" : "DeleteRequestBody",
1175
+ "externalSourceGUID": "add guid here",
1176
+ "externalSourceName": "add qualified name here",
1177
+ "effectiveTime" : "{{$isoTimestamp}}",
1178
+ "forLineage" : false,
1179
+ "forDuplicateProcessing" : false
1180
+ }
1181
+ """
1182
+ url = f"{self.command_root}/external-references/{ext_ref_guid}/delete"
1183
+
1184
+ await self._async_delete_request(url, body, cascade)
1185
+ logger.info(f"Deleted collection {ext_ref_guid} with cascade {cascade}")
1186
+
1187
+ @dynamic_catch
1188
+ def delete_external_reference(self, ext_ref_guid: str, body: dict | DeleteRequestBody = None,
1189
+ cascade: bool = False) -> None:
1190
+ """Delete an external reference..
1191
+
1192
+ Parameters
1193
+ ----------
1194
+ ext_ref_guid: str
1195
+ The guid of the external reference to delete.
1196
+
1197
+ cascade: bool, optional, defaults to True
1198
+ If true, a cascade delete is performed.
1199
+
1200
+ body: dict DeleteRequestBody, optional, default = None
1201
+ A dict representing the details of the relationship.
1202
+
1203
+ Returns
1204
+ -------
1205
+ Nothing
1206
+
1207
+ Raises
1208
+ ------
1209
+ PyegeriaInvalidParameterException
1210
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1211
+ ValidationException
1212
+ Raised by pydantic when the request body is invalid.
1213
+ NotAuthorizedException
1214
+ The principle specified by the user_id does not have authorization for the requested action
1215
+
1216
+ Notes
1217
+ _____
1218
+ JSON Structure looks like:
1219
+ {
1220
+ "class" : "DeleteRequestBody",
1221
+ "externalSourceGUID": "add guid here",
1222
+ "externalSourceName": "add qualified name here",
1223
+ "effectiveTime" : "{{$isoTimestamp}}",
1224
+ "forLineage" : false,
1225
+ "forDuplicateProcessing" : false
1226
+ }
1227
+ """
1228
+ loop = asyncio.get_event_loop()
1229
+ loop.run_until_complete(self._async_delete_external_reference(ext_ref_guid,body, cascade))
1230
+
1231
+
1232
+
1233
+ @dynamic_catch
1234
+ async def _async_find_external_references(self, search_string: str = "*", classification_names: list[str] = None,
1235
+ metadata_element_types: list[str] = EXTERNAL_REFERENCE_TYPES,
1236
+ starts_with: bool = True, ends_with: bool = False, ignore_case: bool = False,
1237
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
1238
+ output_format_set: str | dict = "ExternalReference",
1239
+ body: dict | SearchStringRequestBody = None) -> list | str:
1240
+ """ Returns the list of external references matching the search string filtered by the optional classification.
1241
+ This method can either be used with a body, allowing full control, or with the individual parameters.
1242
+ If the body is provided it will be used and the search_string will be ignored.
1243
+
1244
+ Parameters
1245
+ ----------
1246
+ search_string: str
1247
+ Search string to match against - None or '*' indicate match against all collections (may be filtered by
1248
+ classification).
1249
+ classification_names: list[str], optional, default=None
1250
+ A list of classification names to filter on - for example, ["DataSpec"], for data specifications. If none,
1251
+ then all classifications are returned.
1252
+ metadata_element_types: list[str], optional, default=None
1253
+ A list of metadata element types to filter on - for example, ["DataSpec"], for data specifications. If none,
1254
+ starts_with : bool, [default=False], optional
1255
+ Starts with the supplied string.
1256
+ ends_with : bool, [default=False], optional
1257
+ Ends with the supplied string
1258
+ ignore_case : bool, [default=False], optional
1259
+ Ignore case when searching
1260
+ start_from: int, [default=0], optional
1261
+ When multiple pages of results are available, the page number to start from.
1262
+ page_size: int, [default=None]
1263
+ The number of items to return in a single page. If not specified, the default will be taken from
1264
+ the class instance.
1265
+ output_format: str, default = "JSON"
1266
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
1267
+ output_format_set: str | dict , optional, default = None
1268
+ - The desired output columns/fields to include.
1269
+ body: dict | SearchStringRequestBody, optional, default = None
1270
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
1271
+
1272
+ Returns
1273
+ -------
1274
+ List | str
1275
+
1276
+ Output depends on the output format specified.
1277
+
1278
+ Raises
1279
+ ------
1280
+
1281
+ ValidationError
1282
+ If the client passes incorrect parameters on the request that don't conform to the data model.
1283
+ PyegeriaException
1284
+ Issues raised in communicating or server side processing.
1285
+ NotAuthorizedException
1286
+ The principle specified by the user_id does not have authorization for the requested action
1287
+
1288
+ """
1289
+ url = str(HttpUrl(f"{self.command_root}/external-references/by-search-string"))
1290
+ response = await self._async_find_request(url, _type="ExternalReference", search_string=search_string,
1291
+ _gen_output=self._generate_external_reference_output,
1292
+ classification_names = classification_names,
1293
+ metadata_element_types = metadata_element_types,
1294
+ starts_with = starts_with, ends_with = ends_with, ignore_case = ignore_case,
1295
+ start_from = start_from, page_size = page_size,
1296
+ output_format=output_format, output_format_set=output_format_set,
1297
+ body=body)
1298
+
1299
+ return response
1300
+
1301
+ @dynamic_catch
1302
+ def find_external_references(self, search_string: str = '*', classification_names: str = None,
1303
+ metadata_element_types: list[str] = EXTERNAL_REFERENCE_TYPES, starts_with: bool = True,
1304
+ ends_with: bool = False, ignore_case: bool = False,
1305
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
1306
+ output_format_set: str | dict = "ExternalReference",
1307
+ body: dict | SearchStringRequestBody = None) -> list | str:
1308
+ """ Returns the list of external references matching the search string filtered by the optional classification.
1309
+ This method can either be used with a body, allowing full control, or with the individual parameters.
1310
+ If the body is provided it will be used and the search_string will be ignored.
1311
+
1312
+ Parameters
1313
+ ----------
1314
+ search_string: str
1315
+ Search string to match against - None or '*' indicate match against all collections (may be filtered by
1316
+ classification).
1317
+ classification_names: list[str], optional, default=None
1318
+ A list of classification names to filter on - for example, ["DataSpec"], for data specifications. If none,
1319
+ then all classifications are returned.
1320
+ metadata_element_types: list[str], optional, default=None
1321
+ A list of metadata element types to filter on - for example, ["DataSpec"], for data specifications. If none,
1322
+ then all metadata element types are returned.
1323
+ starts_with : bool, [default=False], optional
1324
+ Starts with the supplied string.
1325
+ ends_with : bool, [default=False], optional
1326
+ Ends with the supplied string
1327
+ ignore_case : bool, [default=False], optional
1328
+ Ignore case when searching
1329
+ start_from: int, [default=0], optional
1330
+ When multiple pages of results are available, the page number to start from.
1331
+ page_size: int, [default=None]
1332
+ The number of items to return in a single page. If not specified, the default will be taken from
1333
+ the class instance.
1334
+ output_format: str, default = "JSON"
1335
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
1336
+ output_format_set: str | dict , optional, default = None
1337
+ - The desired output columns/fields to include.
1338
+ body: dict | SearchStringRequestBody, optional, default = None
1339
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
1340
+
1341
+ Returns
1342
+ -------
1343
+ List | str
1344
+
1345
+ Output depends on the output format specified.
1346
+
1347
+ Raises
1348
+ ------
1349
+
1350
+ ValidationError
1351
+ If the client passes incorrect parameters on the request that don't conform to the data model.
1352
+ PyegeriaException
1353
+ Issues raised in communicating or server side processing.
1354
+ NotAuthorizedException
1355
+ The principle specified by the user_id does not have authorization for the requested action
1356
+
1357
+ Args:
1358
+ classification_names ():
1359
+ metadata_element_types ():
1360
+
1361
+ """
1362
+ return asyncio.get_event_loop().run_until_complete(
1363
+ self._async_find_external_references(search_string, classification_names, metadata_element_types,
1364
+ starts_with, ends_with, ignore_case,
1365
+ start_from, page_size, output_format,
1366
+ output_format_set, body))
1367
+
1368
+
1369
+ @dynamic_catch
1370
+ async def _async_get_external_references_by_name(self, filter_string: str = None, classification_names: list[str] = None,
1371
+ body: dict | FilterRequestBody = None,
1372
+ start_from: int = 0, page_size: int = 0,
1373
+ output_format: str = 'JSON',
1374
+ output_format_set: str | dict = "ExternalReference") -> list | str:
1375
+ """ Returns the list of external references with a particular name.
1376
+
1377
+ Parameters
1378
+ ----------
1379
+ filter_string: str,
1380
+ name to use to find matching collections.
1381
+ classification_names: list[str], optional, default = None
1382
+ type of collection to filter by - e.g., DataDict, Folder, Root
1383
+ body: dict, optional, default = None
1384
+ Provides, a full request body. If specified, the body supercedes the name parameter.
1385
+ start_from: int, [default=0], optional
1386
+ When multiple pages of results are available, the page number to start from.
1387
+ page_size: int, [default=None]
1388
+ The number of items to return in a single page. If not specified, the default will be taken from
1389
+ the class instance.
1390
+ output_format: str, default = "JSON"
1391
+ - one of "DICT", "MERMAID" or "JSON"
1392
+ output_format_set: dict , optional, default = None
1393
+ The desired output columns/fields to include.
1394
+
1395
+ Returns
1396
+ -------
1397
+ List | str
1398
+
1399
+ A list of collections match matching the name. Returns a string if none found.
1400
+
1401
+ Raises
1402
+ ------
1403
+
1404
+ InvalidParameterException
1405
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1406
+ PropertyServerException
1407
+ Raised by the server when an issue arises in processing a valid request
1408
+ NotAuthorizedException
1409
+ The principle specified by the user_id does not have authorization for the requested action
1410
+ """
1411
+ url = str(HttpUrl(f"{self.command_root}/by-name"))
1412
+ response = await self._async_get_name_request(url, _type="Collection",
1413
+ _gen_output=self._generate_external_reference_output,
1414
+ filter_string = filter_string, classification_names = classification_names,
1415
+ start_from = start_from, page_size = page_size,
1416
+ output_format=output_format, output_format_set=output_format_set,
1417
+ body=body)
1418
+
1419
+ return response
1420
+
1421
+
1422
+ def get_external_references_by_name(self, filter_string: str = None, classification_names: list[str] = None,
1423
+ body: dict | FilterRequestBody = None,
1424
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
1425
+ output_format_set: str | dict = "ExternalReference") -> list | str:
1426
+ """Returns the list of external references matching the filter string. Async version.
1427
+ The search string is located in the request body and is interpreted as a plain string.
1428
+ The request parameters, startsWith, endsWith, and ignoreCase can be used to allow a fuzzy search.
1429
+
1430
+ Parameters
1431
+ ----------
1432
+ filter_string: str,
1433
+ name to use to find matching collections.
1434
+ classification_names: list[str], optional, default = None
1435
+ type of collection to filter by - e.g., DataDict, Folder, Root
1436
+ body: dict, optional, default = None
1437
+ Provides, a full request body. If specified, the body supercedes the name parameter.
1438
+ start_from: int, [default=0], optional
1439
+ When multiple pages of results are available, the page number to start from.
1440
+ page_size: int, [default=None]
1441
+ The number of items to return in a single page. If not specified, the default will be taken from
1442
+ the class instance.
1443
+ output_format: str, default = "JSON"
1444
+ - one of "DICT", "MERMAID" or "JSON"
1445
+ output_format_set: str | dict, optional, default = None
1446
+ The desired output columns/fields to include.
1447
+
1448
+ Returns
1449
+ -------
1450
+ List | str
1451
+
1452
+ A list of collections match matching the search string. Returns a string if none found.
1453
+
1454
+ Raises
1455
+ ------
1456
+ PyegeriaException
1457
+
1458
+ """
1459
+ return asyncio.get_event_loop().run_until_complete(
1460
+ self._async_get_external_references_by_name(filter_string, classification_names, body, start_from, page_size,
1461
+ output_format, output_format_set))
1462
+
1463
+
1464
+
1465
+
1466
+ @dynamic_catch
1467
+ async def _async_get_external_reference_by_guid(self, ext_ref_guid: str, element_type: str = None,
1468
+ body: dict | GetRequestBody = None,
1469
+ output_format: str = 'JSON',
1470
+ output_format_set: str | dict = "ExternalReference") -> dict | str:
1471
+ """Return the properties of a specific external reference. Async version.
1472
+
1473
+ Parameters
1474
+ ----------
1475
+ ext_ref_guid: str,
1476
+ unique identifier of the external reference to retrieve.
1477
+ element_type: str, default = None, optional
1478
+ type of externak reference ExternalReference, RelatedMedia, etc.
1479
+ body: dict | GetRequestBody, optional, default = None
1480
+ full request body.
1481
+ output_format: str, default = "JSON"
1482
+ - one of "DICT", "MERMAID" or "JSON"
1483
+ output_format_set: str | dict, optional, default = None
1484
+ The desired output columns/fields to include.
1485
+
1486
+ Returns
1487
+ -------
1488
+ dict | str
1489
+
1490
+ A JSON dict representing the specified collection. Returns a string if none found.
1491
+
1492
+ Raises
1493
+ ------
1494
+
1495
+ InvalidParameterException
1496
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1497
+ PropertyServerException
1498
+ Raised by the server when an issue arises in processing a valid request
1499
+ NotAuthorizedException
1500
+ The principle specified by the user_id does not have authorization for the requested action
1501
+
1502
+ Notes
1503
+ ----
1504
+ Body sample:
1505
+ {
1506
+ "class": "GetRequestBody",
1507
+ "asOfTime": "{{$isoTimestamp}}",
1508
+ "effectiveTime": "{{$isoTimestamp}}",
1509
+ "forLineage": false,
1510
+ "forDuplicateProcessing": false
1511
+ }
1512
+ """
1513
+
1514
+ url = str(HttpUrl(f"{self.command_root}/{ext_ref_guid}/retrieve"))
1515
+ type = element_type if element_type else "ExternalReference"
1516
+
1517
+ response = await self._async_get_guid_request(url, _type=type,
1518
+ _gen_output=self._generate_external_reference_output,
1519
+ output_format=output_format, output_format_set=output_format_set,
1520
+ body=body)
1521
+
1522
+ return response
1523
+
1524
+ @dynamic_catch
1525
+ def get_external_reference_by_guid(self, ext_ref_guid: str, element_type: str = None, body: dict | GetRequestBody= None,
1526
+ output_format: str = 'JSON', output_format_set: 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 element - 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
+ output_format_set: dict , optional, default = None
1540
+ The desired output columns/fields to include.
1541
+
1542
+
1543
+ Returns
1544
+ -------
1545
+ dict | str
1546
+
1547
+ A JSON dict representing the specified collection. Returns a string if none found.
1548
+
1549
+ Raises
1550
+ ------
1551
+
1552
+ InvalidParameterException
1553
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1554
+ PropertyServerException
1555
+ Raised by the server when an issue arises in processing a valid request
1556
+ NotAuthorizedException
1557
+ The principle specified by the user_id does not have authorization for the requested action
1558
+
1559
+ Notes
1560
+ ----
1561
+ Body sample:
1562
+ {
1563
+ "class": "AnyTimeRequestBody",
1564
+ "asOfTime": "{{$isoTimestamp}}",
1565
+ "effectiveTime": "{{$isoTimestamp}}",
1566
+ "forLineage": false,
1567
+ "forDuplicateProcessing": false
1568
+ }
1569
+ """
1570
+ return asyncio.get_event_loop().run_until_complete(
1571
+ self._async_get_external_reference_by_guid(ext_ref_guid, element_type, body,
1572
+ output_format, output_format_set))
1573
+
1574
+
1575
+
1576
+
1577
+
1578
+
1579
+ @dynamic_catch
1580
+ async def _async_update_external_reference_status(self, external_reference_guid: str, status: str = None,
1581
+ body: dict | UpdateStatusRequestBody = None):
1582
+ """Update the status of a external_reference. Async version.
1583
+
1584
+ Parameters
1585
+ ----------
1586
+ external_reference_guid: str
1587
+ The guid of the external_reference to update.
1588
+ status: str, optional
1589
+ The new lifecycle status for the external_reference. Ignored, if the body is provided.
1590
+ body: dict | UpdateStatusRequestBody, optional
1591
+ A structure representing the details of the external_reference to create. If supplied, these details
1592
+ supersede the status parameter provided.
1593
+
1594
+ Returns
1595
+ -------
1596
+ Nothing
1597
+
1598
+ Raises
1599
+ ------
1600
+ InvalidParameterException
1601
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1602
+ PropertyServerException
1603
+ Raised by the server when an issue arises in processing a valid request
1604
+ NotAuthorizedException
1605
+ The principle specified by the user_id does not have authorization for the requested action
1606
+
1607
+ Notes
1608
+ -----
1609
+ JSON Structure looks like:
1610
+ {
1611
+ "class": "UpdateStatusRequestBody",
1612
+ "status": "APPROVED",
1613
+ "externalSourceGUID": "add guid here",
1614
+ "externalSourceName": "add qualified name here",
1615
+ "effectiveTime": "{{$isoTimestamp}}",
1616
+ "forLineage": false,
1617
+ "forDuplicateProcessing": false
1618
+ }
1619
+ """
1620
+
1621
+ url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external-reference-managermetadata-elements/{external_reference_guid}/update-status"
1622
+ await self._async_update_status_request(url, status, body)
1623
+
1624
+
1625
+ @dynamic_catch
1626
+ def update_external_reference_status(self, external_reference_guid: str, status: str = None,
1627
+ body: dict | UpdateStatusRequestBody = None):
1628
+ """Update the status of a DigitalProduct external_reference.
1629
+
1630
+ Parameters
1631
+ ----------
1632
+ external_reference_guid: str
1633
+ The guid of the external_reference to update.
1634
+ status: str, optional
1635
+ The new lifecycle status for the digital product. Ignored, if the body is provided.
1636
+ body: dict | UpdateStatusRequestBody, optional
1637
+ A structure representing the details of the external_reference to create. If supplied, these details
1638
+ supersede the status parameter provided.
1639
+
1640
+ Returns
1641
+ -------
1642
+ Nothing
1643
+
1644
+ Raises
1645
+ ------
1646
+ InvalidParameterException
1647
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1648
+ PropertyServerException
1649
+ Raised by the server when an issue arises in processing a valid request
1650
+ NotAuthorizedException
1651
+ The principle specified by the user_id does not have authorization for the requested action
1652
+
1653
+ Notes
1654
+ -----
1655
+ JSON Structure looks like:
1656
+ {
1657
+ "class": "UpdateStatusRequestBody",
1658
+ "status": "APPROVED",
1659
+ "externalSourceGUID": "add guid here",
1660
+ "externalSourceName": "add qualified name here",
1661
+ "effectiveTime": "{{$isoTimestamp}}",
1662
+ "forLineage": false,
1663
+ "forDuplicateProcessing": false
1664
+ }
1665
+ """
1666
+ loop = asyncio.get_event_loop()
1667
+ loop.run_until_complete(self._async_update_external_reference_status(external_reference_guid, status, body))
1668
+
1669
+
1670
+
1671
+
1672
+
1673
+ def _extract_external_reference_properties(self, element: dict, columns_struct: dict) -> dict:
1674
+ """
1675
+ Extract common properties from a external_reference element and populate into the provided columns_struct.
1676
+
1677
+ Args:
1678
+ element (dict): The external_reference element
1679
+ columns_struct (dict): The columns structure to populate
1680
+
1681
+ Returns:
1682
+ dict: columns_struct with column 'value' fields populated
1683
+ """
1684
+ # First, populate from element.properties using the utility
1685
+ col_data = populate_columns_from_properties(element, columns_struct)
1686
+
1687
+ columns_list = col_data.get("formats", {}).get("columns", [])
1688
+
1689
+ # Populate header-derived values
1690
+ header_props = _extract_referenceable_properties(element)
1691
+ for column in columns_list:
1692
+ key = column.get('key')
1693
+ if key in header_props:
1694
+ column['value'] = header_props.get(key)
1695
+ elif isinstance(key, str) and key.lower() == 'guid':
1696
+ column['value'] = header_props.get('GUID')
1697
+
1698
+ # Derived/computed fields
1699
+ # external_referenceCategories are classifications
1700
+ classification_names = ""
1701
+ classifications = element.get('elementHeader', {}).get("external_referenceCategories", [])
1702
+ for classification in classifications:
1703
+ classification_names += f"{classification['classificationName']}, "
1704
+ if classification_names:
1705
+ for column in columns_list:
1706
+ if column.get('key') == 'classifications':
1707
+ column['value'] = classification_names[:-2]
1708
+ break
1709
+
1710
+ # Populate requested relationship-based columns generically from top-level keys
1711
+ col_data = get_required_relationships(element, col_data)
1712
+
1713
+ # Subject area classification
1714
+ subject_area = element.get('elementHeader', {}).get("subjectArea", "") or ""
1715
+ subj_val = ""
1716
+ if isinstance(subject_area, dict):
1717
+ subj_val = subject_area.get("classificationProperties", {}).get("subjectAreaName", "")
1718
+ for column in columns_list:
1719
+ if column.get('key') == 'subject_area':
1720
+ column['value'] = subj_val
1721
+ break
1722
+
1723
+ # Mermaid graph
1724
+ mermaid_val = element.get('mermaidGraph', "") or ""
1725
+ for column in columns_list:
1726
+ if column.get('key') == 'mermaid':
1727
+ column['value'] = mermaid_val
1728
+ break
1729
+
1730
+ logger.trace(f"Extracted/Populated columns: {col_data}")
1731
+
1732
+ return col_data
1733
+
1734
+
1735
+ def _generate_external_reference_output(self, elements: dict | list[dict], filter: Optional[str],
1736
+ element_type_name: Optional[str], output_format: str = "DICT",
1737
+ output_format_set: dict | str = None) -> str | list[dict]:
1738
+ """ Generate output for external_references in the specified format.
1739
+
1740
+ Args:
1741
+ elements (Union[Dict, List[Dict]]): Dictionary or list of dictionaries containing data field elements
1742
+ filter (Optional[str]): The search string used to find the elements
1743
+ element_type_name (Optional[str]): The type of external_reference
1744
+ output_format (str): The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID, HTML)
1745
+ output_format_set (Optional[dict], optional): List of dictionaries containing column data. Defaults
1746
+ to None.
1747
+
1748
+ Returns:
1749
+ Union[str, List[Dict]]: Formatted output as a string or list of dictionaries
1750
+ """
1751
+ if element_type_name is None:
1752
+ entity_type = "ExternalReference"
1753
+ else:
1754
+ entity_type = element_type_name
1755
+ # First see if the user has specified an output_format_set - either a label or a dict
1756
+ get_additional_props_func = None
1757
+ if output_format_set:
1758
+ if isinstance(output_format_set, str):
1759
+ output_formats = select_output_format_set(output_format_set, output_format)
1760
+ elif isinstance(output_format_set, dict):
1761
+ output_formats = get_output_format_type_match(output_format_set, output_format)
1762
+
1763
+ # If no output_format was set, then use the element_type_name to lookup the output format
1764
+ elif element_type_name:
1765
+ output_formats = select_output_format_set(element_type_name, output_format)
1766
+ else:
1767
+ # fallback to external_references or entity type
1768
+ output_formats = select_output_format_set(entity_type, output_format)
1769
+ if output_formats is None:
1770
+ output_formats = select_output_format_set("Default", output_format)
1771
+
1772
+ if output_formats:
1773
+ get_additional_props_name = output_formats.get("get_additional_props", {}).get("function", None)
1774
+ if isinstance(get_additional_props_name, str):
1775
+ class_name, method_name = get_additional_props_name.split(".")
1776
+ if hasattr(self, method_name):
1777
+ get_additional_props_func = getattr(self, method_name)
1778
+
1779
+ logger.trace(f"Executing generate_external_reference_output for {entity_type}: {output_formats}")
1780
+ return generate_output(
1781
+ elements,
1782
+ filter,
1783
+ entity_type,
1784
+ output_format,
1785
+ self._extract_external_reference_properties,
1786
+ get_additional_props_func,
1787
+ output_formats,
1788
+ )
1789
+
1790
+
1791
+ from typing import Union, Dict, List, Optional
1792
+
1793
+ if __name__ == "__main__":
1794
+ print("Main-Collection Manager")