pyegeria 5.4.3.1__py3-none-any.whl → 5.4.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.
Files changed (35) hide show
  1. commands/cat/debug_log.2025-09-01_07-02-58_818650.log.zip +0 -0
  2. commands/cat/debug_log.log +4242 -8144
  3. md_processing/data/commands.json +1255 -612
  4. md_processing/dr_egeria_inbox/data_spec_test.md +38 -86
  5. md_processing/dr_egeria_inbox/gov_def.md +239 -3
  6. md_processing/dr_egeria_inbox/product.md +6 -6
  7. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:03-product.md +209 -0
  8. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 14:24-product.md +263 -0
  9. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:03-data_spec_test.md +2374 -0
  10. md_processing/dr_egeria_outbox/monday/processed-2025-09-01 16:05-data_spec_test.md +2374 -0
  11. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:28-data_spec_test.md +2321 -0
  12. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:37-data_spec_test.md +2304 -0
  13. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 08:56-data_spec_test.md +2324 -0
  14. md_processing/dr_egeria_outbox/monday/processed-2025-09-02 09:00-data_spec_test.md +2324 -0
  15. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:07-gov_def.md +492 -0
  16. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 13:25-gov_def.md +520 -0
  17. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:43-gov_def.md +636 -0
  18. md_processing/dr_egeria_outbox/tuesday/processed-2025-09-02 16:46-gov_def.md +636 -0
  19. md_processing/md_commands/data_designer_commands.py +88 -153
  20. md_processing/md_commands/product_manager_commands.py +1 -1
  21. md_processing/md_processing_utils/common_md_utils.py +5 -12
  22. pyegeria/___external_references.py +3267 -0
  23. pyegeria/data_designer.py +6 -7
  24. pyegeria/project_manager.py +1 -1
  25. {pyegeria-5.4.3.1.dist-info → pyegeria-5.4.3.3.dist-info}/METADATA +1 -1
  26. {pyegeria-5.4.3.1.dist-info → pyegeria-5.4.3.3.dist-info}/RECORD +29 -21
  27. md_processing/dr_egeria_outbox/friday/processed-2025-08-29 16:30-output_tests.md +0 -103
  28. md_processing/dr_egeria_outbox/friday/processed-2025-08-29 16:40-output_tests.md +0 -115
  29. md_processing/dr_egeria_outbox/friday/processed-2025-08-30 21:15-glossary_test1.md +0 -326
  30. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 13:27-glossary_test1.md +0 -369
  31. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 13:33-glossary_test1.md +0 -392
  32. md_processing/dr_egeria_outbox/friday/processed-2025-08-31 20:57-glossary_test1.md +0 -400
  33. {pyegeria-5.4.3.1.dist-info → pyegeria-5.4.3.3.dist-info}/LICENSE +0 -0
  34. {pyegeria-5.4.3.1.dist-info → pyegeria-5.4.3.3.dist-info}/WHEEL +0 -0
  35. {pyegeria-5.4.3.1.dist-info → pyegeria-5.4.3.3.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,3267 @@
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
+ import inspect
11
+ from datetime import datetime
12
+ from typing import Optional, Annotated, Literal, Union
13
+
14
+ from loguru import logger
15
+ from pydantic import ValidationError, Field, HttpUrl
16
+
17
+ from pyegeria._exceptions_new import PyegeriaInvalidParameterException
18
+ from pyegeria._globals import NO_ELEMENTS_FOUND, NO_GUID_RETURNED, NO_MEMBERS_FOUND
19
+ from pyegeria._output_formats import select_output_format_set, get_output_format_type_match
20
+ from pyegeria.config import settings
21
+ from pyegeria.models import (SearchStringRequestBody, FilterRequestBody, GetRequestBody, NewElementRequestBody,
22
+ ReferenceableProperties, InitialClassifications, TemplateRequestBody,
23
+ UpdateElementRequestBody, UpdateStatusRequestBody, NewRelationshipRequestBody,
24
+ DeleteRequestBody, UpdateRelationshipRequestBody, ResultsRequestBody,
25
+ get_defined_field_values, PyegeriaModel)
26
+ from pyegeria.output_formatter import (generate_output,
27
+ _extract_referenceable_properties, populate_columns_from_properties,
28
+ get_required_relationships)
29
+ from pyegeria.utils import body_slimmer, dynamic_catch
30
+
31
+
32
+ app_settings = settings
33
+ EGERIA_LOCAL_QUALIFIER = app_settings.User_Profile.egeria_local_qualifier
34
+
35
+
36
+ from pyegeria._client_new import Client2
37
+
38
+
39
+ class ExternalReferences(Client2):
40
+ """
41
+ Establish linkage to external references which can be a variety of artifacts. Including media,
42
+ documents, data, and more.
43
+
44
+ Attributes:
45
+
46
+ server_name: str
47
+ The name of the View Server to connect to.
48
+ platform_url : str
49
+ URL of the server platform to connect to
50
+ user_id : str
51
+ The identity of the user calling the method - this sets a default optionally used by the methods
52
+ when the user doesn't pass the user_id on a method call.
53
+ user_pwd: str
54
+ The password associated with the user_id. Defaults to None
55
+ token: str
56
+ An optional bearer token
57
+
58
+ """
59
+
60
+
61
+ def __init__(self, view_server: str, platform_url: str, user_id: str, user_pwd: str = None, token: str = None, ):
62
+ self.view_server = view_server
63
+ self.platform_url = platform_url
64
+ self.user_id = user_id
65
+ self.user_pwd = user_pwd
66
+
67
+
68
+ Client2.__init__(self, view_server, platform_url, user_id, user_pwd, token)
69
+ result = self.get_platform_origin()
70
+ logger.info(f"ExternalReferences initialized, platform origin is: {result}")
71
+ self.command_root: str = (
72
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external-references")
73
+
74
+ @dynamic_catch
75
+ async def _async_create_external_reference(self, body: dict | NewElementRequestBody = None) -> str:
76
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
77
+ and classification will be used to create a simple, self-anchored external_reference.
78
+ Collections: https://egeria-project.org/concepts/external_reference
79
+ Async version.
80
+
81
+ Parameters
82
+ ----------
83
+
84
+
85
+ body: dict | NewElementRequestBody, optional
86
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
87
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
88
+ validated before being used.
89
+
90
+ Returns
91
+ -------
92
+ str - the guid of the created external_reference
93
+
94
+ Raises
95
+ ------
96
+ PyegeriaException
97
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
98
+ Egeria errors.
99
+ ValidationError
100
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
101
+ NotAuthorizedException
102
+ The principle specified by the user_id does not have authorization for the requested action
103
+
104
+ Notes:
105
+ -----
106
+ simple:
107
+ {
108
+ "class": "NewElementRequestBody",
109
+ "isOwnAnchor": true,
110
+ "properties": {
111
+ "class": "ExternalReferenceProperties",
112
+ "qualifiedName": "Must provide a unique name here",
113
+ "name": "Add display name here",
114
+ "description": "Add description of the external_reference here",
115
+ "category": "Add appropriate valid value for type",
116
+ "referenceTitle: "Add reference title here",
117
+ "referenceAbstract": "Add reference abstract here",
118
+ "authors": ["Add author names here"],
119
+ "url": "Add url here",
120
+ "datePublished": "2023-01-01",
121
+ "dateConnected": "2023-01-01",
122
+ "dateCreated": "2023-01-01",
123
+ }
124
+ }
125
+
126
+ anchored:
127
+ {
128
+ "class": "NewElementRequestBody",
129
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
130
+ "isOwnAnchor": false,
131
+ "anchorScopeGUID": "optional GUID of search scope",
132
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
133
+ "parentRelationshipTypeName": "open metadata type name",
134
+ "parentAtEnd1": true,
135
+ "properties": {
136
+ "class": "ExternalReferenceProperties",
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
+ },
149
+ "externalSourceGUID": "add guid here",
150
+ "externalSourceName": "add qualified name here",
151
+ "effectiveTime": "{{$isoTimestamp}}",
152
+ "forLineage": false,
153
+ "forDuplicateProcessing": false
154
+ }
155
+
156
+ """
157
+
158
+ url = f"{self.external_reference_command_root}/external-references"
159
+ response = await self._async_create_collection(body=body)
160
+ return response
161
+
162
+ def create_external_reference(self, body: dict | NewElementRequestBody = None) -> str:
163
+ """ Create a new generic external_reference. If the body is not present, the display_name, description, category,
164
+ and classification will be used to create a simple, self-anchored external_reference.
165
+ Collections: https://egeria-project.org/concepts/external_reference
166
+ Async version.
167
+
168
+ Parameters
169
+ ----------
170
+
171
+
172
+ body: dict | NewElementRequestBody, optional
173
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
174
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
175
+ validated before being used.
176
+
177
+ Returns
178
+ -------
179
+ str - the guid of the created external_reference
180
+
181
+ Raises
182
+ ------
183
+ PyegeriaException
184
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
185
+ Egeria errors.
186
+ ValidationError
187
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
188
+ NotAuthorizedException
189
+ The principle specified by the user_id does not have authorization for the requested action
190
+
191
+ Notes:
192
+ -----
193
+ simple:
194
+ {
195
+ "class": "NewElementRequestBody",
196
+ "isOwnAnchor": true,
197
+ "properties": {
198
+ "class": "ExternalReferenceProperties",
199
+ "qualifiedName": "Must provide a unique name here",
200
+ "name": "Add display name here",
201
+ "description": "Add description of the external_reference here",
202
+ "category": "Add appropriate valid value for type",
203
+ "referenceTitle: "Add reference title here",
204
+ "referenceAbstract": "Add reference abstract here",
205
+ "authors": ["Add author names here"],
206
+ "url": "Add url here",
207
+ "datePublished": "2023-01-01",
208
+ "dateConnected": "2023-01-01",
209
+ "dateCreated": "2023-01-01",
210
+ }
211
+ }
212
+
213
+ anchored:
214
+ {
215
+ "class": "NewElementRequestBody",
216
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
217
+ "isOwnAnchor": false,
218
+ "anchorScopeGUID": "optional GUID of search scope",
219
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
220
+ "parentRelationshipTypeName": "open metadata type name",
221
+ "parentAtEnd1": true,
222
+ "properties": {
223
+ "class": "ExternalReferenceProperties",
224
+ "qualifiedName": "Must provide a unique name here",
225
+ "name": "Add display name here",
226
+ "description": "Add description of the external_reference here",
227
+ "category": "Add appropriate valid value for type",
228
+ "referenceTitle: "Add reference title here",
229
+ "referenceAbstract": "Add reference abstract here",
230
+ "authors": ["Add author names here"],
231
+ "url": "Add url here",
232
+ "datePublished": "2023-01-01",
233
+ "dateConnected": "2023-01-01",
234
+ "dateCreated": "2023-01-01",
235
+ },
236
+ "externalSourceGUID": "add guid here",
237
+ "externalSourceName": "add qualified name here",
238
+ "effectiveTime": "{{$isoTimestamp}}",
239
+ "forLineage": false,
240
+ "forDuplicateProcessing": false
241
+ }
242
+
243
+
244
+ """
245
+
246
+ return asyncio.get_event_loop().run_until_complete(
247
+ self._async_create_external_reference(body))
248
+
249
+ #######
250
+
251
+ @dynamic_catch
252
+ async def _async_create_external_reference_from_template(self, body: TemplateRequestBody | dict) -> str:
253
+ """Create a new metadata element to represent a external_reference using an existing metadata element as a template.
254
+ The template defines additional classifications and relationships that are added to the new external_reference.
255
+ Async version.
256
+
257
+ Parameters
258
+ ----------
259
+
260
+ body: dict
261
+ A dict representing the details of the external_reference to create.
262
+
263
+ Returns
264
+ -------
265
+ str - the guid of the created external_reference
266
+
267
+ Raises
268
+ ------
269
+ InvalidParameterException
270
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
271
+ PropertyServerException
272
+ Raised by the server when an issue arises in processing a valid request
273
+ NotAuthorizedException
274
+ The principle specified by the user_id does not have authorization for the requested action
275
+
276
+ Notes
277
+ -----
278
+ JSON Structure looks like:
279
+
280
+ {
281
+ "class": "TemplateRequestBody",
282
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
283
+ "isOwnAnchor": false,
284
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
285
+ "parentRelationshipTypeName": "open metadata type name",
286
+ "parentAtEnd1": true,
287
+ "templateGUID": "template GUID",
288
+ "replacementProperties": {
289
+ "class": "ElementProperties",
290
+ "propertyValueMap" : {
291
+ "propertyName" : {
292
+ "class": "PrimitiveTypePropertyValue",
293
+ "typeName": "string",
294
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
295
+ "primitiveValue" : "value of property"
296
+ }
297
+ }
298
+ },
299
+ "placeholderPropertyValues" : {
300
+ "placeholderProperty1Name" : "property1Value",
301
+ "placeholderProperty2Name" : "property2Value"
302
+ }
303
+ }
304
+
305
+ """
306
+
307
+ if isinstance(body, TemplateRequestBody):
308
+ validated_body = body
309
+
310
+ elif isinstance(body, dict):
311
+ validated_body = self._template_request_adapter.validate_python(body)
312
+
313
+ url = f"{self.external_reference_command_root}/from-template"
314
+ json_body = validated_body.model_dump_json(indent=2, exclude_none=True)
315
+ logger.info(json_body)
316
+ resp = await self._async_make_request("POST", url, json_body, is_json=True)
317
+ logger.info(f"Create external_reference from template with GUID: {resp.json().get('guid')}")
318
+ return resp.json().get("guid", NO_GUID_RETURNED)
319
+
320
+ def create_external_reference_from_template(self, body: dict) -> str:
321
+ """Create a new metadata element to represent a external_reference using an existing metadata element as a template.
322
+ The template defines additional classifications and relationships that are added to the new external_reference.
323
+
324
+ Parameters
325
+ ----------
326
+ body: dict
327
+ A dict representing the details of the external_reference to create.
328
+
329
+ Returns
330
+ -------
331
+ str - the guid of the created external_reference
332
+
333
+ Raises
334
+ ------
335
+ InvalidParameterException
336
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
337
+ PropertyServerException
338
+ Raised by the server when an issue arises in processing a valid request
339
+ NotAuthorizedException
340
+ The principle specified by the user_id does not have authorization for the requested action
341
+
342
+ Notes
343
+ -----
344
+ JSON Structure looks like:
345
+
346
+ {
347
+ "class": "TemplateRequestBody",
348
+ "anchorGUID": "anchor GUID, if set then isOwnAnchor=false",
349
+ "isOwnAnchor": false,
350
+ "parentGUID": "parent GUID, if set, set all parameters beginning 'parent'",
351
+ "parentRelationshipTypeName": "open metadata type name",
352
+ "parentAtEnd1": true,
353
+ "templateGUID": "template GUID",
354
+ "replacementProperties": {
355
+ "class": "ElementProperties",
356
+ "propertyValueMap" : {
357
+ "propertyName" : {
358
+ "class": "PrimitiveTypePropertyValue",
359
+ "typeName": "string",
360
+ "primitiveTypeCategory" : "OM_PRIMITIVE_TYPE_STRING",
361
+ "primitiveValue" : "value of property"
362
+ }
363
+ }
364
+ },
365
+ "placeholderPropertyValues" : {
366
+ "placeholderProperty1Name" : "property1Value",
367
+ "placeholderProperty2Name" : "property2Value"
368
+ }
369
+ }
370
+ """
371
+ loop = asyncio.get_event_loop()
372
+ resp = loop.run_until_complete(self._async_create_external_reference_from_template(body))
373
+ return resp
374
+
375
+ #
376
+ # Manage external_references
377
+ #
378
+
379
+ @dynamic_catch
380
+ async def _async_update_external_reference(self, external_reference_guid: str,
381
+ body: dict | UpdateElementRequestBody) -> None:
382
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
383
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
384
+ Collections: https://egeria-project.org/concepts/external_reference
385
+
386
+ Async version.
387
+ Parameters
388
+ ----------
389
+ external_reference_guid: str
390
+ The guid of the external_reference to update.
391
+
392
+ body: dict | UpdateElementRequestBody, optional
393
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
394
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
395
+ validated before being used.
396
+ merge_update: bool, optional, default = True
397
+ If true then property changes will be overlaid on top of existing properties. If false, existing
398
+ properties will all be replaced by the set provided in the update request.
399
+
400
+ Returns
401
+ -------
402
+ None
403
+
404
+ Raises
405
+ ------
406
+ PyegeriaException
407
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
408
+ Egeria errors.
409
+ ValidationError
410
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
411
+ NotAuthorizedException
412
+ The principle specified by the user_id does not have authorization for the requested action
413
+
414
+ Notes:
415
+ -----
416
+ simple example:
417
+ {
418
+ "class" : "UpdateElementRequestBody",
419
+ "properties": {
420
+ "class" : "CollectionProperties",
421
+ "qualifiedName": "Must provide a unique name here",
422
+ "name" : "Add display name here",
423
+ "description" : "Add description of the external_reference here",
424
+ "category": "Add appropriate valid value for type"
425
+ },
426
+ "externalSourceGUID": "add guid here",
427
+ "externalSourceName": "add qualified name here",
428
+ "effectiveTime" : "{{$isoTimestamp}}",
429
+ "forLineage" : false,
430
+ "forDuplicateProcessing" : false
431
+ }
432
+ """
433
+
434
+ # try:
435
+
436
+ url = (f"{self.external_reference_command_root}/{external_reference_guid}/update")
437
+ await self._async_update_element_body_request(url, COLLECTION_PROPERTIES_LIST, body)
438
+
439
+ @dynamic_catch
440
+ def update_external_reference(self, external_reference_guid: str, body: dict | NewElementRequestBody) -> None:
441
+ """ Update the properties of a external_reference. Use the correct properties object (CollectionProperties,
442
+ DigitalProductProperties, AgreementProperties, etc), that is appropriate for your element.
443
+ Collections: https://egeria-project.org/concepts/external_reference
444
+
445
+ Parameters
446
+ ----------
447
+ external_reference_guid: str
448
+ The guid of the external_reference to update.
449
+
450
+ body: dict | NewElementRequestBody, optional
451
+ A dict or NewElementRequestBody representing the details of the external_reference to create. If supplied, this
452
+ information will be used to create the external_reference and the other attributes will be ignored. The body is
453
+ validated before being used.
454
+ merge_update: bool, optional, default = True
455
+ If true then property changes will be overlaid on top of existing properties. If false, existing
456
+ properties will all be replaced by the set provided in the update request.
457
+
458
+ Returns
459
+ -------
460
+ None
461
+
462
+ Raises
463
+ ------
464
+ PyegeriaException
465
+ One of the pyegeria exceptions will be raised if there are issues in communications, message format, or
466
+ Egeria errors.
467
+ ValidationError
468
+ Pydantic validation errors are raised if the body does not conform to the NewElementRequestBody.
469
+ NotAuthorizedException
470
+ The principle specified by the user_id does not have authorization for the requested action
471
+
472
+ Notes:
473
+ -----
474
+ simple example:
475
+ {
476
+ "class" : "UpdateElementRequestBody",
477
+ "properties": {
478
+ "class" : "CollectionProperties",
479
+ "qualifiedName": "Must provide a unique name here",
480
+ "name" : "Add display name here",
481
+ "description" : "Add description of the external_reference here",
482
+ "category": "Add appropriate valid value for type"
483
+ },
484
+ "externalSourceGUID": "add guid here",
485
+ "externalSourceName": "add qualified name here",
486
+ "effectiveTime" : "{{$isoTimestamp}}",
487
+ "forLineage" : false,
488
+ "forDuplicateProcessing" : false
489
+ }
490
+ """
491
+
492
+ return asyncio.get_event_loop().run_until_complete(
493
+ self._async_update_external_reference(external_reference_guid, body))
494
+
495
+ def get_attached_external_references(self, parent_guid: str, start_from: int = 0, page_size: int = 0, body: dict = None,
496
+ output_format: str = "JSON", output_format_set: str | dict = None) -> list:
497
+ """Returns the list of external_references that are linked off of the supplied element using the ResourceList
498
+ relationship. Async version.
499
+
500
+ Parameters
501
+ ----------
502
+ parent_guid: str
503
+ The identity of the parent to find linked external_references from.
504
+ start_from: int, [default=0], optional
505
+ When multiple pages of results are available, the page number to start from.
506
+ page_size: int, [default=None]
507
+ The number of items to return in a single page. If not specified, the default will be taken from
508
+ the class instance.
509
+ body: dict, optional, default = None
510
+ If supplied, adds addition request details - for instance, to filter the results on external_referenceType
511
+ output_format: str, default = "JSON"
512
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
513
+ output_format_set: str | dict = None), optional, default = None
514
+ The desired output columns/fields to include.
515
+
516
+
517
+ Returns
518
+ -------
519
+ List
520
+
521
+ A list of external_references linked off of the supplied element.
522
+
523
+ Raises
524
+ ------
525
+
526
+ InvalidParameterException
527
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
528
+ PropertyServerException
529
+ Raised by the server when an issue arises in processing a valid request
530
+ NotAuthorizedException
531
+ The principle specified by the user_id does not have authorization for the requested action
532
+
533
+ Notes
534
+ -----
535
+ Sample body:
536
+ {
537
+ "class": "FilterRequestBody",
538
+ "asOfTime": "{{$isoTimestamp}}",
539
+ "effectiveTime": "{{$isoTimestamp}}",
540
+ "forLineage": false,
541
+ "forDuplicateProcessing": false,
542
+ "limitResultsByStatus": ["ACTIVE"],
543
+ "sequencingOrder": "PROPERTY_ASCENDING",
544
+ "sequencingProperty": "qualifiedName",
545
+ "filter": "Add external_referenceType value here"
546
+ }
547
+
548
+ """
549
+ return asyncio.get_event_loop().run_until_complete(
550
+ self._async_get_attached_external_references(parent_guid, start_from, page_size,
551
+ body, output_format, output_format_set))
552
+
553
+
554
+ @dynamic_catch
555
+ async def _async_find_external_references(self, search_string: str = "*", classification_names: list[str] = None,
556
+ metadata_element_types: list[str] = None,
557
+ starts_with: bool = True, ends_with: bool = False, ignore_case: bool = False,
558
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
559
+ output_format_set: str | dict = None,
560
+ body: dict | SearchStringRequestBody = None) -> list | str:
561
+ """ Returns the list of external_references matching the search string filtered by the optional classification.
562
+ This method can either be used with a body, allowing full control, or with the individual parameters.
563
+ If the body is provided it will be used and the search_string will be ignored.
564
+
565
+ Parameters
566
+ ----------
567
+ search_string: str
568
+ Search string to match against - None or '*' indicate match against all external_references (may be filtered by
569
+ classification).
570
+ classification_names: list[str], optional, default=None
571
+ A list of classification names to filter on - for example, ["DataSpec"], for data specifications. If none,
572
+ then all classifications are returned.
573
+ metadata_element_types: list[str], optional, default=None
574
+ A list of metadata element types to filter on - for example, ["DataSpec"], for data specifications. If none,
575
+ starts_with : bool, [default=False], optional
576
+ Starts with the supplied string.
577
+ ends_with : bool, [default=False], optional
578
+ Ends with the supplied string
579
+ ignore_case : bool, [default=False], optional
580
+ Ignore case when searching
581
+ start_from: int, [default=0], optional
582
+ When multiple pages of results are available, the page number to start from.
583
+ page_size: int, [default=None]
584
+ The number of items to return in a single page. If not specified, the default will be taken from
585
+ the class instance.
586
+ output_format: str, default = "JSON"
587
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
588
+ output_format_set: str | dict , optional, default = None
589
+ - The desired output columns/fields to include.
590
+ body: dict | SearchStringRequestBody, optional, default = None
591
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
592
+
593
+ Returns
594
+ -------
595
+ List | str
596
+
597
+ Output depends on the output format specified.
598
+
599
+ Raises
600
+ ------
601
+
602
+ ValidationError
603
+ If the client passes incorrect parameters on the request that don't conform to the data model.
604
+ PyegeriaException
605
+ Issues raised in communicating or server side processing.
606
+ NotAuthorizedException
607
+ The principle specified by the user_id does not have authorization for the requested action
608
+
609
+ """
610
+ url = str(HttpUrl(f"{self.external_reference_command_root}/by-search-string"))
611
+ response = await self._async_find_request(url, _type="Collection",
612
+ _gen_output=self._generate_external_reference_output,
613
+ search_string = search_string, classification_names = classification_names,
614
+ metadata_element_types = metadata_element_types,
615
+ starts_with = starts_with, ends_with = ends_with, ignore_case = ignore_case,
616
+ start_from = start_from, page_size = page_size,
617
+ output_format=output_format, output_format_set=output_format_set,
618
+ body=body)
619
+
620
+ return response
621
+
622
+ @dynamic_catch
623
+ def find_external_references(self, search_string: str = '*', classification_names: str = None,
624
+ metadata_element_types: list[str] = None, starts_with: bool = True,
625
+ ends_with: bool = False, ignore_case: bool = False,
626
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
627
+ output_format_set: str | dict = None,
628
+ body: dict | SearchStringRequestBody = None) -> list | str:
629
+ """ Returns the list of external_references matching the search string filtered by the optional classification.
630
+ This method can either be used with a body, allowing full control, or with the individual parameters.
631
+ If the body is provided it will be used and the search_string will be ignored.
632
+
633
+ Parameters
634
+ ----------
635
+ search_string: str
636
+ Search string to match against - None or '*' indicate match against all external_references (may be filtered by
637
+ classification).
638
+ classification_names: list[str], optional, default=None
639
+ A list of classification names to filter on - for example, ["DataSpec"], for data specifications. If none,
640
+ then all classifications are returned.
641
+ metadata_element_types: list[str], optional, default=None
642
+ A list of metadata element types to filter on - for example, ["DataSpec"], for data specifications. If none,
643
+ then all metadata element types are returned.
644
+ starts_with : bool, [default=False], optional
645
+ Starts with the supplied string.
646
+ ends_with : bool, [default=False], optional
647
+ Ends with the supplied string
648
+ ignore_case : bool, [default=False], optional
649
+ Ignore case when searching
650
+ start_from: int, [default=0], optional
651
+ When multiple pages of results are available, the page number to start from.
652
+ page_size: int, [default=None]
653
+ The number of items to return in a single page. If not specified, the default will be taken from
654
+ the class instance.
655
+ output_format: str, default = "JSON"
656
+ - one of "MD", "LIST", "FORM", "REPORT", "DICT", "MERMAID" or "JSON"
657
+ output_format_set: str | dict , optional, default = None
658
+ - The desired output columns/fields to include.
659
+ body: dict | SearchStringRequestBody, optional, default = None
660
+ - if provided, the search parameters in the body will supercede other attributes, such as "search_string"
661
+
662
+ Returns
663
+ -------
664
+ List | str
665
+
666
+ Output depends on the output format specified.
667
+
668
+ Raises
669
+ ------
670
+
671
+ ValidationError
672
+ If the client passes incorrect parameters on the request that don't conform to the data model.
673
+ PyegeriaException
674
+ Issues raised in communicating or server side processing.
675
+ NotAuthorizedException
676
+ The principle specified by the user_id does not have authorization for the requested action
677
+
678
+ Args:
679
+ classification_names ():
680
+ metadata_element_types ():
681
+
682
+ """
683
+ return asyncio.get_event_loop().run_until_complete(
684
+ self._async_find_external_references(search_string, classification_names, metadata_element_types,
685
+ starts_with, ends_with, ignore_case,
686
+ start_from, page_size, output_format,
687
+ output_format_set, body))
688
+
689
+
690
+ @dynamic_catch
691
+ async def _async_get_external_references_by_name(self, filter_string: str = None, classification_names: list[str] = None,
692
+ body: dict | FilterRequestBody = None,
693
+ start_from: int = 0, page_size: int = 0,
694
+ output_format: str = 'JSON',
695
+ output_format_set: str | dict = None) -> list | str:
696
+ """ Returns the list of external_references with a particular name.
697
+
698
+ Parameters
699
+ ----------
700
+ name: str,
701
+ name to use to find matching external_references.
702
+ classification_names: list[str], optional, default = None
703
+ type of external_reference to filter by - e.g., DataDict, Folder, Root
704
+ body: dict, optional, default = None
705
+ Provides, a full request body. If specified, the body supercedes the name parameter.
706
+ start_from: int, [default=0], optional
707
+ When multiple pages of results are available, the page number to start from.
708
+ page_size: int, [default=None]
709
+ The number of items to return in a single page. If not specified, the default will be taken from
710
+ the class instance.
711
+ output_format: str, default = "JSON"
712
+ - one of "DICT", "MERMAID" or "JSON"
713
+ output_format_set: dict , optional, default = None
714
+ The desired output columns/fields to include.
715
+
716
+ Returns
717
+ -------
718
+ List | str
719
+
720
+ A list of external_references match matching the name. Returns a string if none found.
721
+
722
+ Raises
723
+ ------
724
+
725
+ InvalidParameterException
726
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
727
+ PropertyServerException
728
+ Raised by the server when an issue arises in processing a valid request
729
+ NotAuthorizedException
730
+ The principle specified by the user_id does not have authorization for the requested action
731
+ """
732
+ url = str(HttpUrl(f"{self.external_reference_command_root}/by-name"))
733
+ response = await self._async_get_name_request(url, _type="Collection",
734
+ _gen_output=self._generate_external_reference_output,
735
+ filter_string = filter_string, classification_names = classification_names,
736
+ start_from = start_from, page_size = page_size,
737
+ output_format=output_format, output_format_set=output_format_set,
738
+ body=body)
739
+
740
+ return response
741
+
742
+
743
+ def get_external_references_by_name(self, name: str = None, classification_names: list[str] = None,
744
+ body: dict | FilterRequestBody = None,
745
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
746
+ output_format_set: str | dict = None) -> list | str:
747
+ """Returns the list of external_references matching the search string. Async version.
748
+ The search string is located in the request body and is interpreted as a plain string.
749
+ The request parameters, startsWith, endsWith, and ignoreCase can be used to allow a fuzzy search.
750
+
751
+ Parameters
752
+ ----------
753
+ name: str,
754
+ name to use to find matching external_references.
755
+ classification_names: list[str], optional, default = None
756
+ type of external_reference to filter by - e.g., DataDict, Folder, Root
757
+ body: dict, optional, default = None
758
+ Provides, a full request body. If specified, the body supercedes the name parameter.
759
+ start_from: int, [default=0], optional
760
+ When multiple pages of results are available, the page number to start from.
761
+ page_size: int, [default=None]
762
+ The number of items to return in a single page. If not specified, the default will be taken from
763
+ the class instance.
764
+ output_format: str, default = "JSON"
765
+ - one of "DICT", "MERMAID" or "JSON"
766
+ output_format_set: str | dict, optional, default = None
767
+ The desired output columns/fields to include.
768
+
769
+ Returns
770
+ -------
771
+ List | str
772
+
773
+ A list of external_references match matching the search string. Returns a string if none found.
774
+
775
+ Raises
776
+ ------
777
+ PyegeriaException
778
+
779
+ """
780
+ return asyncio.get_event_loop().run_until_complete(
781
+ self._async_get_external_references_by_name(name, classification_names, body, start_from, page_size,
782
+ output_format, output_format_set))
783
+
784
+
785
+ @dynamic_catch
786
+ async def _async_get_external_references_by_category(self, category: str, classification_names: list[str] = None,
787
+ body: dict | FilterRequestBody = None, start_from: int = 0, page_size: int = 0,
788
+ output_format: str = 'JSON',
789
+ output_format_set: str | dict = None) -> list | str:
790
+ """Returns the list of external_references with a particular category. This is an optional text field in the
791
+ external_reference element.
792
+
793
+ Parameters
794
+ ----------
795
+ category: str
796
+ category to use to find matching external_references.
797
+ classification_names: str, optional
798
+ An optional filter on the search, e.g., DataSpec
799
+ body: dict, optional, default = None
800
+ Provides, a full request body. If specified, the body filter parameter supercedes the external_reference_type
801
+ parameter.
802
+ start_from: int, [default=0], optional
803
+ When multiple pages of results are available, the page number to start from.
804
+ page_size: int, [default=None]
805
+ The number of items to return in a single page. If not specified, the default will be taken from
806
+ the class instance.
807
+ output_format: str, default = "JSON"
808
+ - one of "DICT", "MERMAID" or "JSON"
809
+ output_format_set: str | dict , optional, default = None
810
+ The desired output columns/fields to include.
811
+
812
+ Returns
813
+ -------
814
+ List | str
815
+
816
+ A list of external_references matching the external_reference type. Returns a string if none found.
817
+
818
+ Raises
819
+ ------
820
+ PyegeriaException
821
+
822
+ Notes
823
+ -----
824
+ Body sample:
825
+
826
+ {
827
+ "class": "FilterRequestBody",
828
+ "asOfTime": "{{$isoTimestamp}}",
829
+ "effectiveTime": "{{$isoTimestamp}}",
830
+ "forLineage": false,
831
+ "forDuplicateProcessing": false,
832
+ "limitResultsByStatus": ["ACTIVE"],
833
+ "sequencingOrder": "PROPERTY_ASCENDING",
834
+ "sequencingProperty": "qualifiedName",
835
+ "filter": "Add category here"
836
+ }
837
+
838
+ """
839
+ url = str(HttpUrl(f"{self.external_reference_command_root}/by-external_reference-category"))
840
+ response = await self._async_get_name_request(url, _type="Collection",
841
+ _gen_output=self._generate_external_reference_output,
842
+ filter_string = category, classification_names = classification_names,
843
+ start_from = start_from, page_size = page_size,
844
+ output_format=output_format, output_format_set=output_format_set,
845
+ body=body)
846
+
847
+ return response
848
+
849
+
850
+
851
+ def get_external_references_by_category(self, category: str, classification_names: list[str] = None,
852
+ body: dict | FilterRequestBody = None,
853
+ start_from: int = 0, page_size: int = 0, output_format: str = 'JSON',
854
+ output_format_set: str | dict = None) -> list | str:
855
+ """Returns the list of external_references with a particular external_referenceType. This is an optional text field in the
856
+ external_reference element.
857
+
858
+ Parameters
859
+ ----------
860
+ category: str
861
+ category to use to find matching external_references.
862
+ classification_names: list[str], optional
863
+ An optional filter on the search, e.g., DataSpec
864
+ body: dict, optional, default = None
865
+ Provides, a full request body. If specified, the body filter parameter supersedes the category
866
+ parameter.
867
+ start_from: int, [default=0], optional
868
+ When multiple pages of results are available, the page number to start from.
869
+ page_size: int, [default=None]
870
+ The number of items to return in a single page. If not specified, the default will be taken from
871
+ the class instance.
872
+ output_format: str, default = "JSON"
873
+ - one of "DICT", "MERMAID" or "JSON"
874
+ output_format_set: str | dict, optional, default = None
875
+ The desired output columns/fields to include.
876
+
877
+ Returns
878
+ -------
879
+ List | str
880
+
881
+ A list of external_references filtered by the specified category. Output based on specified output format.
882
+
883
+ Raises
884
+ ------
885
+
886
+ InvalidParameterException
887
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
888
+ PropertyServerException
889
+ Raised by the server when an issue arises in processing a valid request
890
+ NotAuthorizedException
891
+ The principle specified by the user_id does not have authorization for the requested action
892
+
893
+ Notes
894
+ -----
895
+ Body sample:
896
+
897
+ {
898
+ "class": "FilterRequestBody",
899
+ "asOfTime": "{{$isoTimestamp}}",
900
+ "effectiveTime": "{{$isoTimestamp}}",
901
+ "forLineage": false,
902
+ "forDuplicateProcessing": false,
903
+ "limitResultsByStatus": ["ACTIVE"],
904
+ "sequencingOrder": "PROPERTY_ASCENDING",
905
+ "sequencingProperty": "qualifiedName",
906
+ "filter": "Add category here"
907
+ }
908
+
909
+ """
910
+
911
+ return asyncio.get_event_loop().run_until_complete(
912
+ self._async_get_external_references_by_category(category, classification_names, body, start_from, page_size,
913
+ output_format, output_format_set))
914
+
915
+
916
+ @dynamic_catch
917
+ async def _async_get_external_reference_by_guid(self, external_reference_guid: str, element_type: str = None,
918
+ body: dict | GetRequestBody = None,
919
+ output_format: str = 'JSON',
920
+ output_format_set: str | dict = None) -> dict | str:
921
+ """Return the properties of a specific external_reference. Async version.
922
+
923
+ Parameters
924
+ ----------
925
+ external_reference_guid: str,
926
+ unique identifier of the external_reference.
927
+ element_type: str, default = None, optional
928
+ type of external_reference - Collection, DataSpec, Agreement, etc.
929
+ body: dict | GetRequestBody, optional, default = None
930
+ full request body.
931
+ output_format: str, default = "JSON"
932
+ - one of "DICT", "MERMAID" or "JSON"
933
+ output_format_set: str | dict, optional, default = None
934
+ The desired output columns/fields to include.
935
+
936
+ Returns
937
+ -------
938
+ dict | str
939
+
940
+ A JSON dict representing the specified external_reference. Returns a string if none found.
941
+
942
+ Raises
943
+ ------
944
+
945
+ InvalidParameterException
946
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
947
+ PropertyServerException
948
+ Raised by the server when an issue arises in processing a valid request
949
+ NotAuthorizedException
950
+ The principle specified by the user_id does not have authorization for the requested action
951
+
952
+ Notes
953
+ ----
954
+ Body sample:
955
+ {
956
+ "class": "GetRequestBody",
957
+ "asOfTime": "{{$isoTimestamp}}",
958
+ "effectiveTime": "{{$isoTimestamp}}",
959
+ "forLineage": false,
960
+ "forDuplicateProcessing": false
961
+ }
962
+ """
963
+
964
+ url = str(HttpUrl(f"{self.external_reference_command_root}/{external_reference_guid}/retrieve"))
965
+ type = element_type if element_type else "Collection"
966
+
967
+ response = await self._async_get_guid_request(url, _type=type,
968
+ _gen_output=self._generate_external_reference_output,
969
+ output_format=output_format, output_format_set=output_format_set,
970
+ body=body)
971
+
972
+ return response
973
+
974
+
975
+
976
+
977
+ def get_external_reference_by_guid(self, external_reference_guid: str, element_type: str = None, body: dict | GetRequestBody= None,
978
+ output_format: str = 'JSON', output_format_set: str | dict = None) -> dict | str:
979
+ """ Return the properties of a specific external_reference. Async version.
980
+
981
+ Parameters
982
+ ----------
983
+ external_reference_guid: str,
984
+ unique identifier of the external_reference.
985
+ element_type: str, default = None, optional
986
+ type of element - Collection, DataSpec, Agreement, etc.
987
+ body: dict | GetRequestBody, optional, default = None
988
+ full request body.
989
+ output_format: str, default = "JSON"
990
+ - one of "DICT", "MERMAID" or "JSON"
991
+ output_format_set: dict , optional, default = None
992
+ The desired output columns/fields to include.
993
+
994
+
995
+ Returns
996
+ -------
997
+ dict | str
998
+
999
+ A JSON dict representing the specified external_reference. Returns a string if none found.
1000
+
1001
+ Raises
1002
+ ------
1003
+
1004
+ InvalidParameterException
1005
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1006
+ PropertyServerException
1007
+ Raised by the server when an issue arises in processing a valid request
1008
+ NotAuthorizedException
1009
+ The principle specified by the user_id does not have authorization for the requested action
1010
+
1011
+ Notes
1012
+ ----
1013
+ Body sample:
1014
+ {
1015
+ "class": "AnyTimeRequestBody",
1016
+ "asOfTime": "{{$isoTimestamp}}",
1017
+ "effectiveTime": "{{$isoTimestamp}}",
1018
+ "forLineage": false,
1019
+ "forDuplicateProcessing": false
1020
+ }
1021
+ """
1022
+ return asyncio.get_event_loop().run_until_complete(
1023
+ self._async_get_external_reference_by_guid(external_reference_guid, element_type, body,
1024
+ output_format, output_format_set))
1025
+
1026
+
1027
+
1028
+ @dynamic_catch
1029
+ async def _async_update_external_reference_status(self, external_reference_guid: str, status: str = None,
1030
+ body: dict | UpdateStatusRequestBody = None):
1031
+ """Update the status of a external_reference. Async version.
1032
+
1033
+ Parameters
1034
+ ----------
1035
+ external_reference_guid: str
1036
+ The guid of the external_reference to update.
1037
+ status: str, optional
1038
+ The new lifecycle status for the external_reference. Ignored, if the body is provided.
1039
+ body: dict | UpdateStatusRequestBody, optional
1040
+ A structure representing the details of the external_reference to create. If supplied, these details
1041
+ supersede the status parameter provided.
1042
+
1043
+ Returns
1044
+ -------
1045
+ Nothing
1046
+
1047
+ Raises
1048
+ ------
1049
+ InvalidParameterException
1050
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1051
+ PropertyServerException
1052
+ Raised by the server when an issue arises in processing a valid request
1053
+ NotAuthorizedException
1054
+ The principle specified by the user_id does not have authorization for the requested action
1055
+
1056
+ Notes
1057
+ -----
1058
+ JSON Structure looks like:
1059
+ {
1060
+ "class": "UpdateStatusRequestBody",
1061
+ "status": "APPROVED",
1062
+ "externalSourceGUID": "add guid here",
1063
+ "externalSourceName": "add qualified name here",
1064
+ "effectiveTime": "{{$isoTimestamp}}",
1065
+ "forLineage": false,
1066
+ "forDuplicateProcessing": false
1067
+ }
1068
+ """
1069
+
1070
+ url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/metadata-elements/{external_reference_guid}/update-status"
1071
+ await self._async_update_status_request(url, status, body)
1072
+
1073
+ @dynamic_catch
1074
+ def update_external_reference_status(self, external_reference_guid: str, status: str = None,
1075
+ body: dict | UpdateStatusRequestBody = None):
1076
+ """Update the status of a DigitalProduct external_reference.
1077
+
1078
+ Parameters
1079
+ ----------
1080
+ external_reference_guid: str
1081
+ The guid of the external_reference to update.
1082
+ status: str, optional
1083
+ The new lifecycle status for the digital product. Ignored, if the body is provided.
1084
+ body: dict | UpdateStatusRequestBody, optional
1085
+ A structure representing the details of the external_reference to create. If supplied, these details
1086
+ supersede the status parameter provided.
1087
+
1088
+ Returns
1089
+ -------
1090
+ Nothing
1091
+
1092
+ Raises
1093
+ ------
1094
+ InvalidParameterException
1095
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1096
+ PropertyServerException
1097
+ Raised by the server when an issue arises in processing a valid request
1098
+ NotAuthorizedException
1099
+ The principle specified by the user_id does not have authorization for the requested action
1100
+
1101
+ Notes
1102
+ -----
1103
+ JSON Structure looks like:
1104
+ {
1105
+ "class": "UpdateStatusRequestBody",
1106
+ "status": "APPROVED",
1107
+ "externalSourceGUID": "add guid here",
1108
+ "externalSourceName": "add qualified name here",
1109
+ "effectiveTime": "{{$isoTimestamp}}",
1110
+ "forLineage": false,
1111
+ "forDuplicateProcessing": false
1112
+ }
1113
+ """
1114
+ loop = asyncio.get_event_loop()
1115
+ loop.run_until_complete(self._async_update_external_reference_status(external_reference_guid, status, body))
1116
+
1117
+
1118
+
1119
+ @dynamic_catch
1120
+ async def _async_link_digital_product_dependency(self, upstream_digital_prod_guid: str,
1121
+ downstream_digital_prod_guid: str,
1122
+ body: dict | NewRelationshipRequestBody = None):
1123
+ """ Link two dependent digital products. The linked elements are of type DigitalProduct.
1124
+ Request body is optional. Async version.
1125
+
1126
+ Parameters
1127
+ ----------
1128
+ upstream_digital_prod_guid: str
1129
+ The guid of the first digital product
1130
+ downstream_digital_prod_guid: str
1131
+ The guid of the downstream digital product
1132
+ body: dict | NewRelationshipRequestBody, optional, default = None
1133
+ A dict representing the details of the relationship.
1134
+
1135
+ Returns
1136
+ -------
1137
+ Nothing
1138
+
1139
+ Raises
1140
+ ------
1141
+ InvalidParameterException
1142
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1143
+ PropertyServerException
1144
+ Raised by the server when an issue arises in processing a valid request
1145
+ NotAuthorizedException
1146
+ The principle specified by the user_id does not have authorization for the requested action
1147
+
1148
+ Notes
1149
+ -----
1150
+ JSON Structure looks like:
1151
+ {
1152
+ "class" : "NewRelationshipRequestBody",
1153
+ "externalSourceGUID": "add guid here",
1154
+ "externalSourceName": "add qualified name here",
1155
+ "effectiveTime" : "{{$isoTimestamp}}",
1156
+ "forLineage" : false,
1157
+ "forDuplicateProcessing" : false,
1158
+ "properties": {
1159
+ "class": "InformationSupplyChainLinkProperties",
1160
+ "label": "add label here",
1161
+ "description": "add description here",
1162
+ "effectiveFrom": "{{$isoTimestamp}}",
1163
+ "effectiveTo": "{{$isoTimestamp}}"
1164
+ }
1165
+ }
1166
+ """
1167
+ url = (
1168
+ f"{self.platform_url}/servers/"
1169
+ f"{self.view_server}/api/open-metadata/external_reference-manager/external_references/digital-products/"
1170
+ f"{upstream_digital_prod_guid}/product-dependencies/{downstream_digital_prod_guid}/attach")
1171
+ await self._async_new_relationship_request(url, "InformationSupplyChainLinkProperties", body)
1172
+ logger.info(f"Linked {upstream_digital_prod_guid} -> {downstream_digital_prod_guid}")
1173
+
1174
+
1175
+ def link_digital_product_dependency(self, upstream_digital_prod_guid: str, downstream_digital_prod_guid: str,
1176
+ body: dict | NewRelationshipRequestBody= None):
1177
+ """ Link two dependent digital products. The linked elements are of type DigitalProduct.
1178
+ Request body is optional.
1179
+
1180
+ Parameters
1181
+ ----------
1182
+ upstream_digital_prod_guid: str
1183
+ The guid of the first digital product
1184
+ downstream_digital_prod_guid: str
1185
+ The guid of the downstream digital product
1186
+ body: dict | NewRelationshipRequestBody, optional, default = None
1187
+ A structure representing the details of the relationship.
1188
+
1189
+ Returns
1190
+ -------
1191
+ Nothing
1192
+
1193
+ Raises
1194
+ ------
1195
+ InvalidParameterException
1196
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1197
+ PropertyServerException
1198
+ Raised by the server when an issue arises in processing a valid request
1199
+ NotAuthorizedException
1200
+ The principle specified by the user_id does not have authorization for the requested action
1201
+
1202
+ Notes
1203
+ -----
1204
+ JSON Structure looks like:
1205
+ JSON Structure looks like:
1206
+ {
1207
+ "class" : "NewRelationshipRequestBody",
1208
+ "externalSourceGUID": "add guid here",
1209
+ "externalSourceName": "add qualified name here",
1210
+ "effectiveTime" : "{{$isoTimestamp}}",
1211
+ "forLineage" : false,
1212
+ "forDuplicateProcessing" : false,
1213
+ "properties": {
1214
+ "class": "InformationSupplyChainLinkProperties",
1215
+ "label": "add label here",
1216
+ "description": "add description here",
1217
+ "effectiveFrom": "{{$isoTimestamp}}",
1218
+ "effectiveTo": "{{$isoTimestamp}}"
1219
+ }
1220
+ }
1221
+ """
1222
+ loop = asyncio.get_event_loop()
1223
+ loop.run_until_complete(
1224
+ self._async_link_digital_product_dependency(upstream_digital_prod_guid, downstream_digital_prod_guid,
1225
+ body))
1226
+
1227
+
1228
+ @dynamic_catch
1229
+ async def _async_detach_digital_product_dependency(self, upstream_digital_prod_guid: str,
1230
+ downstream_digital_prod_guid: str,
1231
+ body: dict | DeleteRequestBody = None)-> None:
1232
+ """ Unlink two dependent digital products. The linked elements are of type DigitalProduct.
1233
+ Request body is optional. Async version.
1234
+
1235
+ Parameters
1236
+ ----------
1237
+ upstream_digital_prod_guid: str
1238
+ The guid of the first digital product
1239
+ downstream_digital_prod_guid: str
1240
+ The guid of the downstream digital product
1241
+ body: dict | DeleteRequestBody, optional, default = None
1242
+ A structure representing the details of the relationship.
1243
+
1244
+ Returns
1245
+ -------
1246
+ Nothing
1247
+
1248
+ Raises
1249
+ ------
1250
+ InvalidParameterException
1251
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1252
+ PropertyServerException
1253
+ Raised by the server when an issue arises in processing a valid request
1254
+ NotAuthorizedException
1255
+ The principle specified by the user_id does not have authorization for the requested action
1256
+
1257
+ Notes
1258
+ -----
1259
+ JSON Structure looks like:
1260
+ {
1261
+ "class": "DeleteRequestBody",
1262
+ "externalSourceGUID": "add guid here",
1263
+ "externalSourceName": "add qualified name here",
1264
+ "effectiveTime": "{{$isoTimestamp}}",
1265
+ "forLineage": false,
1266
+ "forDuplicateProcessing": false
1267
+ }
1268
+
1269
+ """
1270
+
1271
+ url = (
1272
+ f"{self.platform_url}/servers/"
1273
+ f"{self.view_server}/api/open-metadata/external_reference-manager/external_references/digital-products/"
1274
+ f"{upstream_digital_prod_guid}/product-dependencies/{downstream_digital_prod_guid}/detach")
1275
+ await self._async_delete_request(url, body)
1276
+ logger.info(f"Detached digital product dependency {upstream_digital_prod_guid} -> {downstream_digital_prod_guid}")
1277
+
1278
+
1279
+ def detach_digital_product_dependency(self, upstream_digital_prod_guid: str, downstream_digital_prod_guid: str,
1280
+ body: dict | DeleteRequestBody= None):
1281
+ """ Unlink two dependent digital products. The linked elements are of type DigitalProduct.
1282
+ Request body is optional.
1283
+
1284
+ Parameters
1285
+ ----------
1286
+ upstream_digital_prod_guid: str
1287
+ The guid of the first digital product
1288
+ downstream_digital_prod_guid: str
1289
+ The guid of the downstream digital product
1290
+ body: dict | DeleteRequestBody, optional, default = None
1291
+ A structure representing the details of the relationship.
1292
+
1293
+ Returns
1294
+ -------
1295
+ Nothing
1296
+
1297
+ Raises
1298
+ ------
1299
+ InvalidParameterException
1300
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1301
+ PropertyServerException
1302
+ Raised by the server when an issue arises in processing a valid request
1303
+ NotAuthorizedException
1304
+ The principle specified by the user_id does not have authorization for the requested action
1305
+
1306
+ Notes
1307
+ -----
1308
+ JSON Structure looks like:
1309
+ {
1310
+ "class": "DeleteRequestBody",
1311
+ "externalSourceGUID": "add guid here",
1312
+ "externalSourceName": "add qualified name here",
1313
+ "effectiveTime": "{{$isoTimestamp}}",
1314
+ "forLineage": false,
1315
+ "forDuplicateProcessing": false
1316
+ }
1317
+ """
1318
+ loop = asyncio.get_event_loop()
1319
+ loop.run_until_complete(
1320
+ self._async_detach_digital_product_dependency(upstream_digital_prod_guid, downstream_digital_prod_guid,
1321
+ body))
1322
+
1323
+
1324
+
1325
+
1326
+
1327
+
1328
+
1329
+ #
1330
+
1331
+ ###
1332
+
1333
+ @dynamic_catch
1334
+ async def _async_link_agreement_item(self, agreement_guid: str, agreement_item_guid: str,
1335
+ body: dict| NewRelationshipRequestBody = None) -> None:
1336
+ """ Attach an agreement to an element referenced in its definition. The agreement item element is of type
1337
+ 'Referenceable' to allow the agreement to refer to many things. Request body is optional. Async version.
1338
+
1339
+ Parameters
1340
+ ----------
1341
+ agreement_guid: str
1342
+ The guid of the agreement to update.
1343
+ agreement_item_guid: str
1344
+ The guid of the element to attach.
1345
+ body: dict | NewRelationshipRequestBody, optional, default = None
1346
+ A dict representing the details of the relationship.
1347
+
1348
+ Returns
1349
+ -------
1350
+ Nothing
1351
+
1352
+ Raises
1353
+ ------
1354
+ InvalidParameterException
1355
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1356
+ PropertyServerException
1357
+ Raised by the server when an issue arises in processing a valid request
1358
+ NotAuthorizedException
1359
+ The principle specified by the user_id does not have authorization for the requested action
1360
+
1361
+ Notes
1362
+ _____
1363
+ {
1364
+ "class" : "NewRelationshipRequestBody",
1365
+ "externalSourceGUID": "add guid here",
1366
+ "externalSourceName": "add qualified name here",
1367
+ "effectiveTime" : "{{$isoTimestamp}}",
1368
+ "forLineage" : false,
1369
+ "forDuplicateProcessing" : false,
1370
+ "properties": {
1371
+ "class": "AgreementItemProperties",
1372
+ "agreementItemId": "add label here",
1373
+ "agreementStart": "{{$isoTimestamp}}",
1374
+ "agreementEnd": "{{$isoTimestamp}}",
1375
+ "restrictions": {
1376
+ "property1Name" : "property1Value",
1377
+ "property2Name" : "property2Value"
1378
+ },
1379
+ "obligations" : {
1380
+ "property1Name" : "property1Value",
1381
+ "property2Name" : "property2Value"
1382
+ },
1383
+ "entitlements" : {
1384
+ "property1Name" : "property1Value",
1385
+ "property2Name" : "property2Value"
1386
+ },
1387
+ "usageMeasurements" : {
1388
+ "property1Name" : "property1Value",
1389
+ "property2Name" : "property2Value"
1390
+ },
1391
+ "effectiveFrom": "{{$isoTimestamp}}",
1392
+ "effectiveTo": "{{$isoTimestamp}}"
1393
+ }
1394
+ }
1395
+
1396
+ """
1397
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references/"
1398
+ f"agreements/{agreement_guid}/agreement-items/{agreement_item_guid}/attach")
1399
+
1400
+ await self._async_new_relationship_request(url, "AgreementItemProperties", body)
1401
+ logger.info(f"Attached agreement item {agreement_item_guid} to {agreement_guid}")
1402
+
1403
+
1404
+ def link_agreement_item(self, agreement_guid: str, agreement_item_guid: str, body: dict = None) -> None:
1405
+ """ Attach an agreement to an element referenced in its definition. The agreement item element is of type
1406
+ 'Referenceable' to allow the agreement to refer to many things. Request body is optional.
1407
+
1408
+ Parameters
1409
+ ----------
1410
+ agreement_guid: str
1411
+ The guid of the agreement to update.
1412
+ agreement_item_guid: str
1413
+ The guid of the element to attach.
1414
+ body: dict, optional, default = None
1415
+ A dict representing the details of the relationship.
1416
+
1417
+ Returns
1418
+ -------
1419
+ Nothing
1420
+
1421
+ Raises
1422
+ ------
1423
+ InvalidParameterException
1424
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1425
+ PropertyServerException
1426
+ Raised by the server when an issue arises in processing a valid request
1427
+ NotAuthorizedException
1428
+ The principle specified by the user_id does not have authorization for the requested action
1429
+
1430
+ Notes
1431
+ _____
1432
+
1433
+ {
1434
+ "class" : "RelationshipRequestBody",
1435
+ "externalSourceGUID": "add guid here",
1436
+ "externalSourceName": "add qualified name here",
1437
+ "effectiveTime" : "{{$isoTimestamp}}",
1438
+ "forLineage" : false,
1439
+ "forDuplicateProcessing" : false,
1440
+ "properties": {
1441
+ "class": "AgreementItemProperties",
1442
+ "agreementItemId": "add label here",
1443
+ "agreementStart": "{{$isoTimestamp}}",
1444
+ "agreementEnd": "{{$isoTimestamp}}",
1445
+ "restrictions": {
1446
+ "property1Name" : "property1Value",
1447
+ "property2Name" : "property2Value"
1448
+ },
1449
+ "obligations" : {
1450
+ "property1Name" : "property1Value",
1451
+ "property2Name" : "property2Value"
1452
+ },
1453
+ "usageMeasurements" : {
1454
+ "property1Name" : "property1Value",
1455
+ "property2Name" : "property2Value"
1456
+ },
1457
+ "effectiveFrom": "{{$isoTimestamp}}",
1458
+ "effectiveTo": "{{$isoTimestamp}}"
1459
+ }
1460
+ }
1461
+
1462
+ """
1463
+ loop = asyncio.get_event_loop()
1464
+ loop.run_until_complete(self._async_link_agreement_item(agreement_guid, agreement_item_guid, body))
1465
+
1466
+
1467
+ @dynamic_catch
1468
+ async def _async_detach_agreement_item(self, agreement_guid: str, agreement_item_guid: str,
1469
+ body: dict | DeleteRequestBody = None) -> None:
1470
+ """Detach an agreement item from an agreement. Request body is optional. Async version.
1471
+
1472
+ Parameters
1473
+ ----------
1474
+ agreement_guid: str
1475
+ The guid of the agreement to link.
1476
+ agreement_item_guid: str
1477
+ The guid of the element to attach.
1478
+ body: dict | DeleteRequestBody, optional, default = None
1479
+ A structure representing the details of the relationship.
1480
+
1481
+ Returns
1482
+ -------
1483
+ Nothing
1484
+
1485
+ Raises
1486
+ ------
1487
+ InvalidParameterException
1488
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1489
+ PropertyServerException
1490
+ Raised by the server when an issue arises in processing a valid request
1491
+ NotAuthorizedException
1492
+ The principle specified by the user_id does not have authorization for the requested action
1493
+
1494
+ Notes
1495
+ _____
1496
+ {
1497
+ "class": "DeleteRequestBody",
1498
+ "externalSourceGUID": "add guid here",
1499
+ "externalSourceName": "add qualified name here",
1500
+ "effectiveTime": "{{$isoTimestamp}}",
1501
+ "forLineage": false,
1502
+ "forDuplicateProcessing": false
1503
+ }
1504
+
1505
+ """
1506
+ url = (
1507
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
1508
+ f"/agreements"
1509
+ f"{agreement_guid}/agreement-items/{agreement_item_guid}/detach")
1510
+ await self._async_delete_request(url, body)
1511
+ logger.info(f"Detached agreement item {agreement_item_guid} from {agreement_guid}")
1512
+
1513
+
1514
+ def detach_agreement_item(self, agreement_guid: str, agreement_item_guid: str, body: dict = None) -> None:
1515
+ """Detach an agreement item from an agreement. Request body is optional. Async version.
1516
+
1517
+ Parameters
1518
+ ----------
1519
+ agreement_guid: str
1520
+ The guid of the agreement to link.
1521
+ agreement_item_guid: str
1522
+ The guid of the element to attach.
1523
+ body: dict, optional, default = None
1524
+ A dict representing the details of the relationship.
1525
+
1526
+ Returns
1527
+ -------
1528
+ Nothing
1529
+
1530
+ Raises
1531
+ ------
1532
+ InvalidParameterException
1533
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1534
+ PropertyServerException
1535
+ Raised by the server when an issue arises in processing a valid request
1536
+ NotAuthorizedException
1537
+ The principle specified by the user_id does not have authorization for the requested action
1538
+
1539
+ Notes
1540
+ _____
1541
+ {
1542
+ "class" : "MetadataSourceRequestBody",
1543
+ "externalSourceGUID": "add guid here",
1544
+ "externalSourceName": "add qualified name here",
1545
+ "effectiveTime" : "{{$isoTimestamp}}",
1546
+ "forLineage" : false,
1547
+ "forDuplicateProcessing" : false
1548
+ }
1549
+
1550
+ """
1551
+ loop = asyncio.get_event_loop()
1552
+ loop.run_until_complete(self._async_detach_agreement_item(agreement_guid, agreement_item_guid, body))
1553
+
1554
+
1555
+ @dynamic_catch
1556
+ async def _async_link_contract(self, agreement_guid: str, external_ref_guid: str,
1557
+ body: dict | NewRelationshipRequestBody = None) -> None:
1558
+ """ Attach an agreement to an external reference element that describes the location of the contract
1559
+ documents.
1560
+ Request body is optional. Async version.
1561
+
1562
+ Parameters
1563
+ ----------
1564
+ agreement_guid: str
1565
+ The guid of the agreement to update.
1566
+ external_ref_guid: str
1567
+ The guid of the external reference to attach.
1568
+ body: dict | NewRelationshipRequestBody, optional, default = None
1569
+ A structure representing the details of the relationship.
1570
+
1571
+ Returns
1572
+ -------
1573
+ Nothing
1574
+
1575
+ Raises
1576
+ ------
1577
+ InvalidParameterException
1578
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1579
+ PropertyServerException
1580
+ Raised by the server when an issue arises in processing a valid request
1581
+ NotAuthorizedException
1582
+ The principle specified by the user_id does not have authorization for the requested action
1583
+
1584
+ Notes
1585
+ _____
1586
+
1587
+ {
1588
+ "class" : "RelationshipRequestBody",
1589
+ "externalSourceGUID": "add guid here",
1590
+ "externalSourceName": "add qualified name here",
1591
+ "effectiveTime" : "{{$isoTimestamp}}",
1592
+ "forLineage" : false,
1593
+ "forDuplicateProcessing" : false,
1594
+ "properties": {
1595
+ "class": "ContractLinkProperties",
1596
+ "contractId": "add id here",
1597
+ "contractLiaison": "add identifier of actor here",
1598
+ "contractLiaisonTypeName": "add type of actor here",
1599
+ "contractLiaisonPropertyName": "add property of actor's identifier here",
1600
+ "effectiveFrom": "{{$isoTimestamp}}",
1601
+ "effectiveTo": "{{$isoTimestamp}}"
1602
+ }
1603
+ }
1604
+
1605
+ """
1606
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references/"
1607
+ f"agreements/{agreement_guid}/contract-links/{external_ref_guid}/attach")
1608
+ await self._async_new_relationship_request(url, "ContractLinkProperties", body)
1609
+ logger.info(f"Attached agreement {agreement_guid} to contract {external_ref_guid}")
1610
+
1611
+ @dynamic_catch
1612
+ def link_contract(self, agreement_guid: str, external_ref_guid: str, body: dict = None) -> None:
1613
+ """ Attach an agreement to an external reference element that describes the location of the contract
1614
+ documents.
1615
+ Request body is optional.
1616
+
1617
+ Parameters
1618
+ ----------
1619
+ agreement_guid: str
1620
+ The guid of the agreement to update.
1621
+ external_ref_guid: str
1622
+ The guid of the external reference to attach.
1623
+ body: dict, optional, default = None
1624
+ A dict representing the details of the relationship.
1625
+
1626
+ Returns
1627
+ -------
1628
+ Nothing
1629
+
1630
+ Raises
1631
+ ------
1632
+ InvalidParameterException
1633
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1634
+ PropertyServerException
1635
+ Raised by the server when an issue arises in processing a valid request
1636
+ NotAuthorizedException
1637
+ The principle specified by the user_id does not have authorization for the requested action
1638
+
1639
+ Notes
1640
+ _____
1641
+
1642
+ {
1643
+ "class" : "RelationshipRequestBody",
1644
+ "externalSourceGUID": "add guid here",
1645
+ "externalSourceName": "add qualified name here",
1646
+ "effectiveTime" : "{{$isoTimestamp}}",
1647
+ "forLineage" : false,
1648
+ "forDuplicateProcessing" : false,
1649
+ "properties": {
1650
+ "class": "ContractLinkProperties",
1651
+ "contractId": "add id here",
1652
+ "contractLiaison": "add identifier of actor here",
1653
+ "contractLiaisonTypeName": "add type of actor here",
1654
+ "contractLiaisonPropertyName": "add property of actor's identifier here",
1655
+ "effectiveFrom": "{{$isoTimestamp}}",
1656
+ "effectiveTo": "{{$isoTimestamp}}"
1657
+ }
1658
+ }
1659
+
1660
+ """
1661
+ loop = asyncio.get_event_loop()
1662
+ loop.run_until_complete(self._async_link_contract(agreement_guid, external_ref_guid, body))
1663
+
1664
+
1665
+ @dynamic_catch
1666
+ async def _async_detach_contract(self, agreement_guid: str, external_ref_guid: str, body: dict = None) -> None:
1667
+ """Detach an external reference to a contract, from an agreement. Request body is optional. Async version.
1668
+
1669
+ Parameters
1670
+ ----------
1671
+ agreement_guid: str
1672
+ The guid of the agreement to link.
1673
+ external_ref_guid: str
1674
+ The guid of the element to attach.
1675
+ body: dict, optional, default = None
1676
+ A dict representing the details of the relationship.
1677
+
1678
+ Returns
1679
+ -------
1680
+ Nothing
1681
+
1682
+ Raises
1683
+ ------
1684
+ InvalidParameterException
1685
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1686
+ PropertyServerException
1687
+ Raised by the server when an issue arises in processing a valid request
1688
+ NotAuthorizedException
1689
+ The principle specified by the user_id does not have authorization for the requested action
1690
+
1691
+ Notes
1692
+ _____
1693
+ {
1694
+ "class" : "MetadataSourceRequestBody",
1695
+ "externalSourceGUID": "add guid here",
1696
+ "externalSourceName": "add qualified name here",
1697
+ "effectiveTime" : "{{$isoTimestamp}}",
1698
+ "forLineage" : false,
1699
+ "forDuplicateProcessing" : false
1700
+ }
1701
+
1702
+ """
1703
+
1704
+ url = (
1705
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
1706
+ f"/agreements/{agreement_guid}/contract-links/{external_ref_guid}/detach")
1707
+ await self._async_delete_request(url, body)
1708
+ logger.info(f"Detached contract: {external_ref_guid} from {agreement_guid}")
1709
+
1710
+ @dynamic_catch
1711
+ def detach_contract(self, agreement_guid: str, external_ref_guid: str, body: dict = None) -> None:
1712
+ """Detach an external reference to a contract, from an agreement. Request body is optional.
1713
+
1714
+ Parameters
1715
+ ----------
1716
+ agreement_guid: str
1717
+ The guid of the agreement to link.
1718
+ external_ref_guid: str
1719
+ The guid of the element to attach.
1720
+ body: dict, optional, default = None
1721
+ A dict representing the details of the relationship.
1722
+
1723
+ Returns
1724
+ -------
1725
+ Nothing
1726
+
1727
+ Raises
1728
+ ------
1729
+ InvalidParameterException
1730
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1731
+ PropertyServerException
1732
+ Raised by the server when an issue arises in processing a valid request
1733
+ NotAuthorizedException
1734
+ The principle specified by the user_id does not have authorization for the requested action
1735
+
1736
+ Notes
1737
+ _____
1738
+ {
1739
+ "class" : "MetadataSourceRequestBody",
1740
+ "externalSourceGUID": "add guid here",
1741
+ "externalSourceName": "add qualified name here",
1742
+ "effectiveTime" : "{{$isoTimestamp}}",
1743
+ "forLineage" : false,
1744
+ "forDuplicateProcessing" : false
1745
+ }
1746
+
1747
+ """
1748
+ loop = asyncio.get_event_loop()
1749
+ loop.run_until_complete(self._async_detach_contract(agreement_guid, external_ref_guid, body))
1750
+
1751
+ #
1752
+ # Digital Subscriptions
1753
+ #
1754
+
1755
+
1756
+ @dynamic_catch
1757
+ async def _async_create_digital_subscription(self, body: dict | NewElementRequestBody) -> str:
1758
+ """Create a new external_reference that represents a type of agreement called a digital_subscription. Async version.
1759
+
1760
+ Parameters
1761
+ ----------
1762
+ body | NewElementRequewstBody: dict
1763
+ A structure representing the details of the external_reference to create.
1764
+
1765
+ Returns
1766
+ -------
1767
+ str - the guid of the created external_reference
1768
+
1769
+ Raises
1770
+ ------
1771
+ InvalidParameterException
1772
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1773
+ PropertyServerException
1774
+ Raised by the server when an issue arises in processing a valid request
1775
+ NotAuthorizedException
1776
+ The principle specified by the user_id does not have authorization for the requested action
1777
+
1778
+ Notes
1779
+ -----
1780
+ Note: the three dates: introductionDate, nextVersionDate, and withdrawDate must
1781
+ be valid dates if specified, otherwise you will get a 400 error response.
1782
+
1783
+ JSON Structure looks like:
1784
+ {
1785
+ "class" : "NewElementRequestBody",
1786
+ "isOwnAnchor" : true,
1787
+ "anchorScopeGUID" : "optional GUID of search scope",
1788
+ "parentGUID" : "xxx",
1789
+ "parentRelationshipTypeName" : "CollectionMembership",
1790
+ "parentAtEnd1": true,
1791
+ "properties": {
1792
+ "class" : "DigitalSubscriptionProperties",
1793
+ "qualifiedName": "DigitalSubscription::Add subscription name here",
1794
+ "name" : "display name",
1795
+ "description" : "Add description of the subscription here",
1796
+ "userDefinedStatus" : "OBSOLETE",
1797
+ "identifier" : "Add subscription identifier here",
1798
+ "supportLevel" : "Add the level of support agreed/requested",
1799
+ "serviceLevels" : {
1800
+ "property1Name" : "property1Value",
1801
+ "property2Name" : "property2Value"
1802
+ },
1803
+ "additionalProperties": {
1804
+ "property1Name" : "property1Value",
1805
+ "property2Name" : "property2Value"
1806
+ }
1807
+ },
1808
+ "externalSourceGUID": "add guid here",
1809
+ "externalSourceName": "add qualified name here",
1810
+ "effectiveTime" : "{{$isoTimestamp}}",
1811
+ "forLineage" : false,
1812
+ "forDuplicateProcessing" : false
1813
+ }
1814
+
1815
+ With a lifecycle, the body is:
1816
+
1817
+ The DigitalSubscription is a type of Agreement and so can have lifecycle states.
1818
+ Note: the three dates: introductionDate, nextVersionDate, and withdrawDate must be valid dates if specified,
1819
+ otherwise you will get a 400 error response.
1820
+ The valid values for initialStatus are: DRAFT, PREPARED, PROPOSED, APPROVED, REJECTED
1821
+ ACTIVE, DEPRECATED, OTHER. If using OTHER, set the userDefinedStatus with the statu value you want.
1822
+
1823
+ {
1824
+ "class" : "NewAgreementRequestBody",
1825
+ "isOwnAnchor" : true,
1826
+ "anchorScopeGUID" : "optional GUID of search scope",
1827
+ "parentGUID" : "xxx",
1828
+ "parentRelationshipTypeName" : "CollectionMembership",
1829
+ "parentAtEnd1": true,
1830
+ "properties": {
1831
+ "class" : "DigitalSubscriptionProperties",
1832
+ "qualifiedName": "DigitalSubscription::Add subscription name here",
1833
+ "name" : "display name",
1834
+ "description" : "Add description of the subscription here",
1835
+ "userDefinedStatus" : "OBSOLETE",
1836
+ "identifier" : "Add subscription identifier here",
1837
+ "supportLevel" : "Add the level of support agreed/requested",
1838
+ "serviceLevels" : {
1839
+ "property1Name" : "property1Value",
1840
+ "property2Name" : "property2Value"
1841
+ },
1842
+ "additionalProperties": {
1843
+ "property1Name" : "property1Value",
1844
+ "property2Name" : "property2Value"
1845
+ }
1846
+ },
1847
+ "initialStatus" : "OTHER",
1848
+ "externalSourceGUID": "add guid here",
1849
+ "externalSourceName": "add qualified name here",
1850
+ "effectiveTime" : "{{$isoTimestamp}}",
1851
+ "forLineage" : false,
1852
+ "forDuplicateProcessing" : false
1853
+ }
1854
+ """
1855
+ url = f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
1856
+ return await self._async_create_element_body_request(url, "DigitalSubscriptionProperties", body)
1857
+
1858
+
1859
+ def create_digital_subscription(self, body: dict) -> str:
1860
+ """Create a new external_reference that represents a type of agreement called a digital_subscription.
1861
+
1862
+ Parameters
1863
+ ----------
1864
+ body: dict
1865
+ A dict representing the details of the external_reference to create.
1866
+
1867
+ Returns
1868
+ -------
1869
+ str - the guid of the created external_reference
1870
+
1871
+ Raises
1872
+ ------
1873
+ InvalidParameterException
1874
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1875
+ PropertyServerException
1876
+ Raised by the server when an issue arises in processing a valid request
1877
+ NotAuthorizedException
1878
+ The principle specified by the user_id does not have authorization for the requested action
1879
+
1880
+ Notes
1881
+ -----
1882
+ Note: the three dates: introductionDate, nextVersionDate, and withdrawDate must
1883
+ be valid dates if specified, otherwise you will get a 400 error response.
1884
+
1885
+ JSON Structure looks like:
1886
+ With a lifecycle, the body is:
1887
+
1888
+ The DigitalSubscription is a type of Agreement and so can have lifecycle states.
1889
+ Note: the three dates: introductionDate, nextVersionDate, and withdrawDate must be valid dates if specified,
1890
+ otherwise you will get a 400 error response.
1891
+ The valid values for initialStatus are: DRAFT, PREPARED, PROPOSED, APPROVED, REJECTED
1892
+ ACTIVE, DEPRECATED, OTHER. If using OTHER, set the userDefinedStatus with the statu value you want.
1893
+
1894
+ {
1895
+ "class" : "NewAgreementRequestBody",
1896
+ "isOwnAnchor" : true,
1897
+ "anchorScopeGUID" : "optional GUID of search scope",
1898
+ "parentGUID" : "xxx",
1899
+ "parentRelationshipTypeName" : "CollectionMembership",
1900
+ "parentAtEnd1": true,
1901
+ "properties": {
1902
+ "class" : "DigitalSubscriptionProperties",
1903
+ "qualifiedName": "DigitalSubscription::Add subscription name here",
1904
+ "name" : "display name",
1905
+ "description" : "Add description of the subscription here",
1906
+ "userDefinedStatus" : "OBSOLETE",
1907
+ "identifier" : "Add subscription identifier here",
1908
+ "supportLevel" : "Add the level of support agreed/requested",
1909
+ "serviceLevels" : {
1910
+ "property1Name" : "property1Value",
1911
+ "property2Name" : "property2Value"
1912
+ },
1913
+ "additionalProperties": {
1914
+ "property1Name" : "property1Value",
1915
+ "property2Name" : "property2Value"
1916
+ }
1917
+ },
1918
+ "initialStatus" : "OTHER",
1919
+ "externalSourceGUID": "add guid here",
1920
+ "externalSourceName": "add qualified name here",
1921
+ "effectiveTime" : "{{$isoTimestamp}}",
1922
+ "forLineage" : false,
1923
+ "forDuplicateProcessing" : false
1924
+ }
1925
+ """
1926
+ loop = asyncio.get_event_loop()
1927
+ resp = loop.run_until_complete(self._async_create_digital_subscription(body))
1928
+ return resp
1929
+
1930
+
1931
+ @dynamic_catch
1932
+ async def _async_update_digital_subscription(self, digital_subscription_guid: str,
1933
+ body: dict | UpdateElementRequestBody) -> None:
1934
+ """Update the properties of the digital_subscription external_reference. Async version.
1935
+
1936
+ Parameters
1937
+ ----------
1938
+ digital_subscription_guid: str
1939
+ The guid of the digital_subscription to update.
1940
+ body: dict | UpdateElementRequestBody
1941
+ A structure representing the details of the external_reference to create.
1942
+
1943
+ Returns
1944
+ -------
1945
+ Nothing
1946
+
1947
+ Raises
1948
+ ------
1949
+ InvalidParameterException
1950
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
1951
+ PropertyServerException
1952
+ Raised by the server when an issue arises in processing a valid request
1953
+ NotAuthorizedException
1954
+ The principle specified by the user_id does not have authorization for the requested action
1955
+
1956
+ Notes
1957
+ -----
1958
+ JSON Structure looks like:
1959
+ {
1960
+ "class" : "UpdateElementRequestBody",
1961
+ "properties": {
1962
+ "class" : "DigitalSubscriptionProperties",
1963
+ "qualifiedName": "DigitalSubscription::Add subscription name here",
1964
+ "name" : "display name",
1965
+ "description" : "Add description of the subscription here",
1966
+ "userDefinedStatus" : "OBSOLETE",
1967
+ "identifier" : "Add subscription identifier here",
1968
+ "supportLevel" : "Add the level of support agreed/requested",
1969
+ "serviceLevels" : {
1970
+ "property1Name" : "property1Value",
1971
+ "property2Name" : "property2Value"
1972
+ },
1973
+ "additionalProperties": {
1974
+ "property1Name" : "property1Value",
1975
+ "property2Name" : "property2Value"
1976
+ }
1977
+ },
1978
+ "externalSourceGUID": "add guid here",
1979
+ "externalSourceName": "add qualified name here",
1980
+ "effectiveTime" : "{{$isoTimestamp}}",
1981
+ "forLineage" : false,
1982
+ "forDuplicateProcessing" : false
1983
+ }
1984
+ """
1985
+ url = (f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references/"
1986
+ f"{digital_subscription_guid}/update")
1987
+ await self._async_update_element_body_request(url,["DigitalSubscriptionProperties"], body )
1988
+ logger.info(f"Updated digital subscription {digital_subscription_guid}")
1989
+
1990
+ @dynamic_catch
1991
+ def update_digital_subscription(self, digital_subscription_guid: str, body: dict,):
1992
+ """Update the properties of the DigitalProduct classification attached to a external_reference.
1993
+
1994
+ Parameters
1995
+ ----------
1996
+ digital_subscription_guid: str
1997
+ The guid of the digital_subscription to update.
1998
+ body: dict
1999
+ A dict representing the details of the external_reference to create.
2000
+ replace_all_props: bool, optional, defaults to False
2001
+ Whether to replace all properties in the external_reference.
2002
+
2003
+
2004
+ Returns
2005
+ -------
2006
+ Nothing
2007
+
2008
+ Raises
2009
+ ------
2010
+ InvalidParameterException
2011
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2012
+ PropertyServerException
2013
+ Raised by the server when an issue arises in processing a valid request
2014
+ NotAuthorizedException
2015
+ The principle specified by the user_id does not have authorization for the requested action
2016
+
2017
+ Notes
2018
+ -----
2019
+ JSON Structure looks like:
2020
+ {
2021
+ "class" : "UpdateElementRequestBody",
2022
+ "properties": {
2023
+ "class" : "AgreementProperties",
2024
+ "qualifiedName": "Agreement::Add digital_subscription name here",
2025
+ "name" : "display name",
2026
+ "description" : "Add description of the digital_subscription here",
2027
+ "userDefinedStatus" : "OBSOLETE",
2028
+ "identifier" : "Add digital_subscription identifier here",
2029
+ "additionalProperties": {
2030
+ "property1Name" : "property1Value",
2031
+ "property2Name" : "property2Value"
2032
+ }
2033
+ },
2034
+ "externalSourceGUID": "add guid here",
2035
+ "externalSourceName": "add qualified name here",
2036
+ "effectiveTime" : "{{$isoTimestamp}}",
2037
+ "forLineage" : false,
2038
+ "forDuplicateProcessing" : false
2039
+ }
2040
+
2041
+ """
2042
+ loop = asyncio.get_event_loop()
2043
+ loop.run_until_complete(
2044
+ self._async_update_digital_subscription(digital_subscription_guid, body))
2045
+
2046
+
2047
+ @dynamic_catch
2048
+ async def _async_update_digital_subscription_status(self, digital_subscription_guid: str, status: str = None,
2049
+ body: dict | UpdateStatusRequestBody = None)-> None:
2050
+ """Update the status of a digital_subscription external_reference. Async version.
2051
+
2052
+ Parameters
2053
+ ----------
2054
+ digital_subscription_guid: str
2055
+ The guid of the digital product external_reference to update.
2056
+ status: str, optional
2057
+ The new status of the digital_subscription external_reference. Will be used only if body is not provided.
2058
+ body: dict | UpdateStatusRequestBody, optional, defaults to None
2059
+ A structure representing the details of the external_reference to create.
2060
+
2061
+ Returns
2062
+ -------
2063
+ Nothing
2064
+
2065
+ Raises
2066
+ ------
2067
+ InvalidParameterException
2068
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2069
+ PropertyServerException
2070
+ Raised by the server when an issue arises in processing a valid request
2071
+ NotAuthorizedException
2072
+ The principle specified by the user_id does not have authorization for the requested action
2073
+
2074
+ Notes
2075
+ -----
2076
+ JSON Structure looks like:
2077
+ {
2078
+ "class": "UpdateStatusRequestBody",
2079
+ "status": "APPROVED",
2080
+ "externalSourceGUID": "add guid here",
2081
+ "externalSourceName": "add qualified name here",
2082
+ "effectiveTime": "{{$isoTimestamp}}",
2083
+ "forLineage": false,
2084
+ "forDuplicateProcessing": false
2085
+ }
2086
+ """
2087
+ url = (
2088
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
2089
+ f"/agreements/"
2090
+ f"{digital_subscription_guid}/update-status")
2091
+ await self._async_update_status_request(url, status, body)
2092
+ logger.info(f"Updated status for DigitalProduct {digital_subscription_guid}")
2093
+
2094
+ @dynamic_catch
2095
+ def update_digital_subscription_status(self, digital_subscription_guid: str,
2096
+ body: dict | UpdateStatusRequestBody = None,):
2097
+ """Update the status of an digital_subscription external_reference. Async version.
2098
+
2099
+ Parameters
2100
+ ----------
2101
+ digital_subscription_guid: str
2102
+ The guid of the digital product external_reference to update.
2103
+ body: dict
2104
+ A dict representing the details of the external_reference to create.
2105
+
2106
+ Returns
2107
+ -------
2108
+ Nothing
2109
+
2110
+ Raises
2111
+ ------
2112
+ InvalidParameterException
2113
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2114
+ PropertyServerException
2115
+ Raised by the server when an issue arises in processing a valid request
2116
+ NotAuthorizedException
2117
+ The principle specified by the user_id does not have authorization for the requested action
2118
+
2119
+ Notes
2120
+ -----
2121
+ JSON Structure looks like:
2122
+ {
2123
+ "class": "AgreementStatusRequestBody",
2124
+ "status": "APPROVED",
2125
+ "externalSourceGUID": "add guid here",
2126
+ "externalSourceName": "add qualified name here",
2127
+ "effectiveTime": "{{$isoTimestamp}}",
2128
+ "forLineage": false,
2129
+ "forDuplicateProcessing": false
2130
+ }
2131
+
2132
+ """
2133
+ loop = asyncio.get_event_loop()
2134
+ loop.run_until_complete(self._async_update_digital_subscription_status(digital_subscription_guid, body))
2135
+
2136
+
2137
+ @dynamic_catch
2138
+ async def _async_link_subscriber(self, subscriber_guid: str, subscription_guid: str,
2139
+ body: dict | NewRelationshipRequestBody = None)-> None:
2140
+ """ Attach a subscriber to a subscription. The subscriber is of type 'Referenceable' to allow digital
2141
+ products, team, or business capabilities to be the subscriber. The subscription is an element of type
2142
+ DigitalSubscription.
2143
+ Async version.
2144
+
2145
+ Parameters
2146
+ ----------
2147
+ subscriber_guid: str
2148
+ The unique identifier of the subscriber.
2149
+ subscription_guid: str
2150
+ The identifier of the subscription.
2151
+ body: dict | NewRelationshipRequestBody, optional, default = None
2152
+ A structure representing the details of the relationship.
2153
+
2154
+ Returns
2155
+ -------
2156
+ Nothing
2157
+
2158
+ Raises
2159
+ ------
2160
+ InvalidParameterException
2161
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2162
+ PropertyServerException
2163
+ Raised by the server when an issue arises in processing a valid request
2164
+ NotAuthorizedException
2165
+ The principle specified by the user_id does not have authorization for the requested action
2166
+
2167
+ Notes
2168
+ -----
2169
+ JSON Structure looks like:
2170
+ {
2171
+ "class" : "NewRelationshipRequestBody",
2172
+ "externalSourceGUID": "add guid here",
2173
+ "externalSourceName": "add qualified name here",
2174
+ "effectiveTime" : "{{$isoTimestamp}}",
2175
+ "forLineage" : false,
2176
+ "forDuplicateProcessing" : false,
2177
+ "properties": {
2178
+ "class": "DigitalSubscriberProperties",
2179
+ "subscriberId": "add id here",
2180
+ "effectiveFrom": "{{$isoTimestamp}}",
2181
+ "effectiveTo": "{{$isoTimestamp}}"
2182
+ }
2183
+ }
2184
+ """
2185
+ url = (
2186
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
2187
+ f"/subscribers/"
2188
+ f"{subscriber_guid}/subscriptions/{subscription_guid}/attach")
2189
+ await self._async_new_relationship_request(url, "DigitalSubscriberProperties", body)
2190
+ logger.info(f"Linking subscriber {subscriber_guid} to subscription {subscription_guid}")
2191
+
2192
+ @dynamic_catch
2193
+ def link_subscriber(self, subscriber_guid: str, subscription_guid: str,
2194
+ body: dict | NewRelationshipRequestBody = None):
2195
+ """ Attach a subscriber to a subscription. The subscriber is of type 'Referenceable' to allow digital
2196
+ products, team, or business capabilities to be the subscriber. The subscription is an element of type
2197
+ DigitalSubscription.
2198
+ Async version.
2199
+
2200
+ Parameters
2201
+ ----------
2202
+ subscriber_guid: str
2203
+ The unique identifier of the subscriber.
2204
+ subscription_guid: str
2205
+ The identifier of the subscription.
2206
+ body: dict, optional, default = None
2207
+ A dict representing the details of the relationship.
2208
+
2209
+ Returns
2210
+ -------
2211
+ Nothing
2212
+
2213
+ Raises
2214
+ ------
2215
+ InvalidParameterException
2216
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2217
+ PropertyServerException
2218
+ Raised by the server when an issue arises in processing a valid request
2219
+ NotAuthorizedException
2220
+ The principle specified by the user_id does not have authorization for the requested action
2221
+
2222
+ Notes
2223
+ -----
2224
+ JSON Structure looks like:
2225
+ {
2226
+ "class" : "RelationshipRequestBody",
2227
+ "externalSourceGUID": "add guid here",
2228
+ "externalSourceName": "add qualified name here",
2229
+ "effectiveTime" : "{{$isoTimestamp}}",
2230
+ "forLineage" : false,
2231
+ "forDuplicateProcessing" : false,
2232
+ "properties": {
2233
+ "class": "DigitalSubscriberProperties",
2234
+ "subscriberId": "add id here",
2235
+ "effectiveFrom": "{{$isoTimestamp}}",
2236
+ "effectiveTo": "{{$isoTimestamp}}"
2237
+ }
2238
+ }
2239
+ """
2240
+ loop = asyncio.get_event_loop()
2241
+ loop.run_until_complete(self._async_link_subscriber(subscriber_guid, subscription_guid, body))
2242
+
2243
+
2244
+ @dynamic_catch
2245
+ async def _async_detach_subscriber(self, subscriber_guid: str, subscription_guid: str,
2246
+ body: dict | DeleteRequestBody = None) -> None:
2247
+ """ Detach a subscriber from a subscription Request body is optional. Async version.
2248
+
2249
+ Parameters
2250
+ ----------
2251
+ subscriber_guid: str
2252
+ The unique identifier of the subscriber.
2253
+ subscription_guid: str
2254
+ The unique identifier of the subscription.
2255
+ body: dict | DeleteRequestBody, optional, default = None
2256
+ A structure representing the details of the relationship.
2257
+
2258
+ Returns
2259
+ -------
2260
+ Nothing
2261
+
2262
+ Raises
2263
+ ------
2264
+ InvalidParameterException
2265
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2266
+ PropertyServerException
2267
+ Raised by the server when an issue arises in processing a valid request
2268
+ NotAuthorizedException
2269
+ The principle specified by the user_id does not have authorization for the requested action
2270
+
2271
+ Notes
2272
+ -----
2273
+ JSON Structure looks like:
2274
+ {
2275
+ "class": "MetadataSourceRequestBody",
2276
+ "externalSourceGUID": "add guid here",
2277
+ "externalSourceName": "add qualified name here",
2278
+ "effectiveTime": "{{$isoTimestamp}}",
2279
+ "forLineage": false,
2280
+ "forDuplicateProcessing": false
2281
+ }
2282
+ """
2283
+ url = (
2284
+ f"{self.platform_url}/servers/{self.view_server}/api/open-metadata/external_reference-manager/external_references"
2285
+ f"/agreements/"
2286
+ f"{subscriber_guid}/agreement-actors/{subscription_guid}/detach")
2287
+ await self._async_delete_request(url, body)
2288
+ logger.info(f"Detached subscriber {subscriber_guid} from subscription {subscription_guid}")
2289
+
2290
+
2291
+ def detach_subscriber(self, subscriber_guid: str, subscription_guid: str, body: dict | DeleteRequestBody= None):
2292
+ """ Detach a subscriber from a subscription. Request body is optional.
2293
+
2294
+ Parameters
2295
+ ----------
2296
+ subscriber_guid: str
2297
+ The unique identifier of the subscriber.
2298
+ subscription_guid: str
2299
+ The unique identifier of the subscription.
2300
+ body: dict, optional, default = None
2301
+ A dict representing the details of the relationship.
2302
+
2303
+ Returns
2304
+ -------
2305
+ Nothing
2306
+
2307
+ Raises
2308
+ ------
2309
+ InvalidParameterException
2310
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2311
+ PropertyServerException
2312
+ Raised by the server when an issue arises in processing a valid request
2313
+ NotAuthorizedException
2314
+ The principle specified by the user_id does not have authorization for the requested action
2315
+
2316
+ Notes
2317
+ -----
2318
+ JSON Structure looks like:
2319
+ {
2320
+ "class": "MetadataSourceRequestBody",
2321
+ "externalSourceGUID": "add guid here",
2322
+ "externalSourceName": "add qualified name here",
2323
+ "effectiveTime": "{{$isoTimestamp}}",
2324
+ "forLineage": false,
2325
+ "forDuplicateProcessing": false
2326
+ }
2327
+ """
2328
+ loop = asyncio.get_event_loop()
2329
+ loop.run_until_complete(self._async_detach_subscriber(subscriber_guid, subscription_guid, body))
2330
+
2331
+ #
2332
+ #
2333
+ #
2334
+
2335
+
2336
+ @dynamic_catch
2337
+ async def _async_attach_external_reference(self, parent_guid: str, external_reference_guid: str,
2338
+ body: dict | NewRelationshipRequestBody= None):
2339
+ """ Connect an existing external_reference to an element using the ResourceList relationship (0019).
2340
+ Async version.
2341
+
2342
+ Parameters
2343
+ ----------
2344
+ parent_guid: str
2345
+ The unique identifier of the parent to attach to.
2346
+ external_reference_guid: str
2347
+ The identifier of the external_reference being attached.
2348
+ body: dict | NewRelationshipRequestBody, optional, default = None
2349
+ A structure representing the details of the relationship.
2350
+
2351
+ Returns
2352
+ -------
2353
+ Nothing
2354
+
2355
+ Raises
2356
+ ------
2357
+ InvalidParameterException
2358
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2359
+ PropertyServerException
2360
+ Raised by the server when an issue arises in processing a valid request
2361
+ NotAuthorizedException
2362
+ The principle specified by the user_id does not have authorization for the requested action
2363
+
2364
+ Notes
2365
+ -----
2366
+ JSON Structure looks like:
2367
+
2368
+ {
2369
+ "class" : "NewRelationshipRequestBody",
2370
+ "properties": {
2371
+ "class": "ResourceListProperties",
2372
+ "resourceUse": "Add valid value here",
2373
+ "resourceUseDescription": "Add description here",
2374
+ "watchResource": false,
2375
+ "resourceUseProperties": {
2376
+ "property1Name": "property1Value",
2377
+ "property2Name": "property2Value"
2378
+ }
2379
+ },
2380
+ "externalSourceGUID": "add guid here",
2381
+ "externalSourceName": "add qualified name here",
2382
+ "effectiveTime" : "{{$isoTimestamp}}",
2383
+ "forLineage" : false,
2384
+ "forDuplicateProcessing" : false
2385
+ }
2386
+
2387
+ """
2388
+
2389
+ url = (
2390
+ f"{self.platform_url}/servers/"
2391
+ f"{self.view_server}/api/open-metadata/external_reference-manager/metadata-elements/"
2392
+ f"{parent_guid}/external_references/{external_reference_guid}/attach")
2393
+ await self._async_new_relationship_request(url, "ResourceListProperties", body)
2394
+ logger.info(f"Attached {external_reference_guid} to {parent_guid}")
2395
+
2396
+ @dynamic_catch
2397
+ def attach_external_reference(self, parent_guid: str, external_reference_guid: str,
2398
+ body: dict | NewRelationshipRequestBody = None):
2399
+ """ Connect an existing external_reference to an element using the ResourceList relationship (0019).
2400
+
2401
+ Parameters
2402
+ ----------
2403
+ parent_guid: str
2404
+ The unique identifier of the parent to attach to.
2405
+ external_reference_guid: str
2406
+ The identifier of the external_reference being attached.
2407
+ body: dict, optional, default = None
2408
+ A dict representing the details of the relationship.
2409
+ make_anchor: bool, optional, default = False
2410
+ Indicates if the external_reference should be anchored to the element.
2411
+
2412
+ Returns
2413
+ -------
2414
+ Nothing
2415
+
2416
+ Raises
2417
+ ------
2418
+ InvalidParameterException
2419
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2420
+ PropertyServerException
2421
+ Raised by the server when an issue arises in processing a valid request
2422
+ NotAuthorizedException
2423
+ The principle specified by the user_id does not have authorization for the requested action
2424
+
2425
+ Notes
2426
+ -----
2427
+ JSON Structure looks like:
2428
+
2429
+ {
2430
+ "class" : "RelationshipRequestBody",
2431
+ "properties": {
2432
+ "class": "ResourceListProperties",
2433
+ "resourceUse": "Add valid value here",
2434
+ "resourceUseDescription": "Add description here",
2435
+ "watchResource": false,
2436
+ "resourceUseProperties": {
2437
+ "property1Name": "property1Value",
2438
+ "property2Name": "property2Value"
2439
+ }
2440
+ },
2441
+ "externalSourceGUID": "add guid here",
2442
+ "externalSourceName": "add qualified name here",
2443
+ "effectiveTime" : "{{$isoTimestamp}}",
2444
+ "forLineage" : false,
2445
+ "forDuplicateProcessing" : false
2446
+ }
2447
+ """
2448
+ loop = asyncio.get_event_loop()
2449
+ loop.run_until_complete(self._async_attach_external_reference(parent_guid, external_reference_guid, body))
2450
+
2451
+
2452
+ @dynamic_catch
2453
+ async def _async_detach_external_reference(self, parent_guid: str, external_reference_guid: str,
2454
+ body: dict | DeleteRequestBody = None):
2455
+ """ Detach an existing external_reference from an element. If the external_reference is anchored to the element,
2456
+ it is delete.
2457
+ Async version.
2458
+
2459
+ Parameters
2460
+ ----------
2461
+ parent_guid: str
2462
+ The unique identifier of the parent to detach from.
2463
+ external_reference_guid: str
2464
+ The identifier of the external_reference being detached.
2465
+ body: dict | DeleteRequestBody, optional, default = None
2466
+ A structure representing the details of the relationship.
2467
+
2468
+
2469
+ Returns
2470
+ -------
2471
+ Nothing
2472
+
2473
+ Raises
2474
+ ------
2475
+ InvalidParameterException
2476
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2477
+ PropertyServerException
2478
+ Raised by the server when an issue arises in processing a valid request
2479
+ NotAuthorizedException
2480
+ The principle specified by the user_id does not have authorization for the requested action
2481
+
2482
+ Notes
2483
+ -----
2484
+ JSON Structure looks like:
2485
+ {
2486
+ "class": "DeleteRequestBody",
2487
+ "externalSourceGUID": "add guid here",
2488
+ "externalSourceName": "add qualified name here",
2489
+ "effectiveTime": "{{$isoTimestamp}}",
2490
+ "forLineage": false,
2491
+ "forDuplicateProcessing": false
2492
+ }
2493
+
2494
+ """
2495
+ url = (
2496
+ f"{self.platform_url}/servers/"
2497
+ f"{self.view_server}/api/open-metadata/external_reference-manager/metadata-elements/"
2498
+ f"{parent_guid}/external_references/{external_reference_guid}/detach")
2499
+ await self._async_delete_request(url, body)
2500
+ logger.info(f"Detached external_reference {external_reference_guid} from {parent_guid}")
2501
+
2502
+
2503
+ def detach_external_reference(self, parent_guid: str, external_reference_guid: str,
2504
+ body: dict | DeleteRequestBody = None):
2505
+ """ Detach an existing external_reference from an element. If the external_reference is anchored to the element,
2506
+ it is delete.
2507
+
2508
+ Parameters
2509
+ ----------
2510
+ parent_guid: str
2511
+ The unique identifier of the parent to detach from.
2512
+ external_reference_guid: str
2513
+ The identifier of the external_reference being detached.
2514
+ body: dict, optional, default = None
2515
+ A dict representing the details of the relationship.
2516
+
2517
+ Returns
2518
+ -------
2519
+ Nothing
2520
+
2521
+ Raises
2522
+ ------
2523
+ InvalidParameterException
2524
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2525
+ PropertyServerException
2526
+ Raised by the server when an issue arises in processing a valid request
2527
+ NotAuthorizedException
2528
+ The principle specified by the user_id does not have authorization for the requested action
2529
+
2530
+ Notes
2531
+ -----
2532
+ JSON Structure looks like:
2533
+ {
2534
+ "class": "MetadataSourceRequestBody",
2535
+ "externalSourceGUID": "add guid here",
2536
+ "externalSourceName": "add qualified name here",
2537
+ "effectiveTime": "{{$isoTimestamp}}",
2538
+ "forLineage": false,
2539
+ "forDuplicateProcessing": false
2540
+ }
2541
+ """
2542
+ loop = asyncio.get_event_loop()
2543
+ loop.run_until_complete(self._async_detach_external_reference(parent_guid, external_reference_guid, body))
2544
+
2545
+
2546
+ @dynamic_catch
2547
+ async def _async_delete_external_reference(self, external_reference_guid: str, body: dict | DeleteRequestBody= None,
2548
+ cascade: bool = False) -> None:
2549
+ """Delete a external_reference. It is detected from all parent elements. If members are anchored to the external_reference
2550
+ then they are also deleted. Async version
2551
+
2552
+
2553
+ Parameters
2554
+ ----------
2555
+ external_reference_guid: str
2556
+ The guid of the external_reference to delete.
2557
+
2558
+ cascade: bool, optional, defaults to True
2559
+ If true, a cascade delete is performed.
2560
+
2561
+ body: dict | DeleteRequestBody, optional, default = None
2562
+ A structure representing the details of the relationship.
2563
+
2564
+ Returns
2565
+ -------
2566
+ Nothing
2567
+
2568
+ Raises
2569
+ ------
2570
+ InvalidParameterException
2571
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2572
+ PropertyServerException
2573
+ Raised by the server when an issue arises in processing a valid request
2574
+ NotAuthorizedException
2575
+ The principle specified by the user_id does not have authorization for the requested action
2576
+
2577
+ Notes
2578
+ _____
2579
+ JSON Structure looks like:
2580
+ {
2581
+ "class": "DeleteRequestBody",
2582
+ "externalSourceGUID": "add guid here",
2583
+ "externalSourceName": "add qualified name here",
2584
+ "effectiveTime": "{{$isoTimestamp}}",
2585
+ "forLineage": false,
2586
+ "forDuplicateProcessing": false
2587
+ }
2588
+
2589
+
2590
+ """
2591
+ url = f"{self.external_reference_command_root}/{external_reference_guid}/delete"
2592
+ await self._async_delete_request(url, body, cascade)
2593
+ logger.info(f"Deleted external_reference {external_reference_guid} with cascade {cascade}")
2594
+
2595
+
2596
+ def delete_external_reference(self, external_reference_guid: str, body: dict | DeleteRequestBody = None,
2597
+ cascade: bool = False) -> None:
2598
+ """Delete a external_reference. It is deleted from all parent elements. If members are anchored to the external_reference
2599
+ then they are also deleted.
2600
+
2601
+ Parameters
2602
+ ----------
2603
+ external_reference_guid: str
2604
+ The guid of the external_reference to delete.
2605
+
2606
+ cascade: bool, optional, defaults to True
2607
+ If true, a cascade delete is performed.
2608
+
2609
+ body: dict DeleteRequestBodyt, optional, default = None
2610
+ A dict representing the details of the relationship.
2611
+
2612
+ Returns
2613
+ -------
2614
+ Nothing
2615
+
2616
+ Raises
2617
+ ------
2618
+ InvalidParameterException
2619
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2620
+ PropertyServerException
2621
+ Raised by the server when an issue arises in processing a valid request
2622
+ NotAuthorizedException
2623
+ The principle specified by the user_id does not have authorization for the requested action
2624
+
2625
+ Notes
2626
+ _____
2627
+ JSON Structure looks like:
2628
+
2629
+
2630
+
2631
+ """
2632
+ loop = asyncio.get_event_loop()
2633
+ loop.run_until_complete(self._async_delete_external_reference(external_reference_guid, body, cascade))
2634
+
2635
+
2636
+ @dynamic_catch
2637
+ async def _async_add_to_external_reference(self, external_reference_guid: str, element_guid: str,
2638
+ body: dict | NewRelationshipRequestBody = None, ) -> None:
2639
+ """Add an element to a external_reference. The request body is optional. Async version.
2640
+
2641
+ Parameters
2642
+ ----------
2643
+ external_reference_guid: str
2644
+ identity of the external_reference to return members for.
2645
+ element_guid: str
2646
+ Effective time of the query. If not specified will default to any time.
2647
+ body: dict NewRelationshipRequestBody, optional, defaults to None
2648
+ The body of the request to add to the external_reference. See notes.
2649
+
2650
+ Returns
2651
+ -------
2652
+ None
2653
+
2654
+ Raises
2655
+ ------
2656
+
2657
+ InvalidParameterException
2658
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2659
+ PropertyServerException
2660
+ Raised by the server when an issue arises in processing a valid request
2661
+ NotAuthorizedException
2662
+ The principle specified by the user_id does not have authorization for the requested action
2663
+
2664
+ Notes
2665
+ -----
2666
+ Example body:
2667
+ { "class": "NewRelationshipRequestBody",
2668
+ "properties" : {
2669
+ "class" : "CollectionMembershipProperties",
2670
+ "membershipRationale": "xxx",
2671
+ "createdBy": "user id here",
2672
+ "expression": "expression that described why the element is a part of this external_reference",
2673
+ "confidence": 100,
2674
+ "status": "PROPOSED",
2675
+ "userDefinedStatus": "Add valid value here",
2676
+ "steward": "identifier of steward that validated this member",
2677
+ "stewardTypeName": "type name of element identifying the steward",
2678
+ "stewardPropertyName": "property name if the steward's identifier",
2679
+ "source": "source of the member",
2680
+ "notes": "Add notes here"
2681
+ },
2682
+ },
2683
+ "externalSourceGUID": "add guid here",
2684
+ "externalSourceName": "add qualified name here",
2685
+ "effectiveTime" : "{{$isoTimestamp}}",
2686
+ "forLineage" : false,
2687
+ "forDuplicateProcessing" : false
2688
+ }
2689
+
2690
+ """
2691
+
2692
+ url = (f"{self.external_reference_command_root}/{external_reference_guid}/members/"
2693
+ f"{element_guid}/attach")
2694
+ await self._async_new_relationship_request(url, "CollectionMembershipProperties", body)
2695
+ logger.info(f"Added {element_guid} to {external_reference_guid}")
2696
+
2697
+
2698
+ def add_to_external_reference(self, external_reference_guid: str, element_guid: str,
2699
+ body: dict | NewRelationshipRequestBody= None, ) -> None:
2700
+ """Add an element to a external_reference. The request body is optional.
2701
+
2702
+ Parameters
2703
+ ----------
2704
+ external_reference_guid: str
2705
+ identity of the external_reference to return members for.
2706
+ element_guid: str
2707
+ Effective time of the query. If not specified will default to any time.
2708
+ body: dict, optional, defaults to None
2709
+ The body of the request to add to the external_reference. See notes.
2710
+
2711
+ The name of the server to use.
2712
+
2713
+
2714
+ Returns
2715
+ -------
2716
+ None
2717
+
2718
+ Raises
2719
+ ------
2720
+
2721
+ InvalidParameterException
2722
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2723
+ PropertyServerException
2724
+ Raised by the server when an issue arises in processing a valid request
2725
+ NotAuthorizedException
2726
+ The principle specified by the user_id does not have authorization for the requested action
2727
+
2728
+ Notes
2729
+ -----
2730
+ Example body:
2731
+ { "class": "RelationshipRequestBody",
2732
+ "properties" : {
2733
+ "class" : "CollectionMembershipProperties",
2734
+ "membershipRationale": "xxx",
2735
+ "createdBy": "user id here",
2736
+ "expression": "expression that described why the element is a part of this external_reference",
2737
+ "confidence": 100,
2738
+ "status": "PROPOSED",
2739
+ "userDefinedStatus": "Add valid value here",
2740
+ "steward": "identifier of steward that validated this member",
2741
+ "stewardTypeName": "type name of element identifying the steward",
2742
+ "stewardPropertyName": "property name if the steward's identifier",
2743
+ "source": "source of the member",
2744
+ "notes": "Add notes here"
2745
+ },
2746
+ },
2747
+ "externalSourceGUID": "add guid here",
2748
+ "externalSourceName": "add qualified name here",
2749
+ "effectiveTime" : "{{$isoTimestamp}}",
2750
+ "forLineage" : false,
2751
+ "forDuplicateProcessing" : false
2752
+ }
2753
+
2754
+ """
2755
+ loop = asyncio.get_event_loop()
2756
+ loop.run_until_complete(self._async_add_to_external_reference(external_reference_guid, element_guid, body))
2757
+
2758
+ def add_term_to_folder(self, folder_guid: str, term_guid: str,
2759
+ body: dict | NewRelationshipRequestBody = None) -> None:
2760
+ """Add a term to a category. The request body is optional."""
2761
+ loop = asyncio.get_event_loop()
2762
+ loop.run_until_complete(self._async_add_to_external_reference(folder_guid, term_guid, body))
2763
+
2764
+
2765
+ @dynamic_catch
2766
+ async def _async_update_external_reference_membership_prop(self, external_reference_guid: str, element_guid: str, body: dict = None,
2767
+ ) -> None:
2768
+ """Update an element's membership to a external_reference. Async version.
2769
+
2770
+ Parameters
2771
+ ----------
2772
+ external_reference_guid: str
2773
+ identity of the external_reference to return members for.
2774
+ element_guid: str
2775
+ Effective time of the query. If not specified will default to any time.
2776
+ body: dict, optional, defaults to None
2777
+ The body of the request to add to the external_reference. See notes.
2778
+ replace_all_props: bool, optional, defaults to False
2779
+ Replace all properties or just update ones specified in body.
2780
+
2781
+ The name of the server to use.
2782
+
2783
+
2784
+ Returns
2785
+ -------
2786
+ None
2787
+
2788
+ Raises
2789
+ ------
2790
+
2791
+ InvalidParameterException
2792
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2793
+ PropertyServerException
2794
+ Raised by the server when an issue arises in processing a valid request
2795
+ NotAuthorizedException
2796
+ The principle specified by the user_id does not have authorization for the requested action
2797
+
2798
+ Notes
2799
+ -----
2800
+ Example body:
2801
+ {
2802
+ "class" : "RelationshipRequestBody",
2803
+ "properties" : {
2804
+ "class": "CollectionMembershipProperties",
2805
+ "membershipRationale": "xxx",
2806
+ "createdBy": "user id here",
2807
+ "expression": "expression that described why the element is a part of this external_reference",
2808
+ "confidence": 100,
2809
+ "membershipStatus": "PROPOSED",
2810
+ "userDefinedStatus": "Add valid value here",
2811
+ "steward": "identifier of steward that validated this member",
2812
+ "stewardTypeName": "type name of element identifying the steward",
2813
+ "stewardPropertyName": "property name if the steward's identifier",
2814
+ "source": "source of the member",
2815
+ "notes": "Add notes here"
2816
+ },
2817
+ "externalSourceGUID": "add guid here",
2818
+ "externalSourceName": "add qualified name here",
2819
+ "effectiveTime" : "{{$isoTimestamp}}",
2820
+ "forLineage" : false,
2821
+ "forDuplicateProcessing" : false
2822
+ }
2823
+ """
2824
+
2825
+ url = (f"{self.external_reference_command_root}/{external_reference_guid}/members/"
2826
+ f"{element_guid}/update")
2827
+ await self._async_update_relationship_request(url, "CollectionMembershipProperties", body )
2828
+ logger.info(f"Updated membership for external_reference {external_reference_guid}")
2829
+
2830
+
2831
+ def update_external_reference_membership_prop(self, external_reference_guid: str, element_guid: str,
2832
+ body: dict | UpdateRelationshipRequestBody= None,
2833
+ ) -> None:
2834
+ """Update an element's membership to a external_reference.
2835
+
2836
+ Parameters
2837
+ ----------
2838
+ external_reference_guid: str
2839
+ identity of the external_reference to return members for.
2840
+ element_guid: str
2841
+ Effective time of the query. If not specified will default to any time.
2842
+ body: dict, optional, defaults to None
2843
+ The body of the request to add to the external_reference. See notes.
2844
+ replace_all_props: bool, optional, defaults to False
2845
+ Replace all properties or just update ones specified in body.
2846
+
2847
+ The name of the server to use.
2848
+
2849
+
2850
+ Returns
2851
+ -------
2852
+ None
2853
+
2854
+ Raises
2855
+ ------
2856
+
2857
+ InvalidParameterException
2858
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2859
+ PropertyServerException
2860
+ Raised by the server when an issue arises in processing a valid request
2861
+ NotAuthorizedException
2862
+ The principle specified by the user_id does not have authorization for the requested action
2863
+
2864
+ Notes
2865
+ -----
2866
+ Example body:
2867
+ {
2868
+ "class" : "RelationshipRequestBody",
2869
+ "properties" : {
2870
+ "class": "CollectionMembershipProperties",
2871
+ "membershipRationale": "xxx",
2872
+ "createdBy": "user id here",
2873
+ "expression": "expression that described why the element is a part of this external_reference",
2874
+ "confidence": 100,
2875
+ "membershipStatus": "PROPOSED",
2876
+ "userDefinedStatus": "Add valid value here",
2877
+ "steward": "identifier of steward that validated this member",
2878
+ "stewardTypeName": "type name of element identifying the steward",
2879
+ "stewardPropertyName": "property name if the steward's identifier",
2880
+ "source": "source of the member",
2881
+ "notes": "Add notes here"
2882
+ },
2883
+ "externalSourceGUID": "add guid here",
2884
+ "externalSourceName": "add qualified name here",
2885
+ "effectiveTime" : "{{$isoTimestamp}}",
2886
+ "forLineage" : false,
2887
+ "forDuplicateProcessing" : false
2888
+ }
2889
+ """
2890
+ loop = asyncio.get_event_loop()
2891
+ loop.run_until_complete(
2892
+ self._async_update_external_reference_membership(external_reference_guid, element_guid, body))
2893
+
2894
+
2895
+ @dynamic_catch
2896
+ async def _async_remove_from_external_reference(self, external_reference_guid: str, element_guid: str,
2897
+ body: dict | DeleteRequestBody = None) -> None:
2898
+ """Remove an element from a external_reference. Async version.
2899
+
2900
+ Parameters
2901
+ ----------
2902
+ external_reference_guid: str
2903
+ identity of the external_reference to return members for.
2904
+ element_guid: str
2905
+ Effective time of the query. If not specified will default to any time.
2906
+ body: dict | DeleteRequestBody, optional, defaults to None
2907
+ The body of the request to add to the external_reference. See notes.
2908
+
2909
+ Returns
2910
+ -------
2911
+ None
2912
+
2913
+ Raises
2914
+ ------
2915
+
2916
+ InvalidParameterException
2917
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2918
+ PropertyServerException
2919
+ Raised by the server when an issue arises in processing a valid request
2920
+ NotAuthorizedException
2921
+ The principle specified by the user_id does not have authorization for the requested action
2922
+
2923
+ Notes
2924
+ -----
2925
+ {
2926
+ "class" : "DeleteRequestBody",
2927
+ "externalSourceGUID": "add guid here",
2928
+ "externalSourceName": "add qualified name here",
2929
+ "effectiveTime" : "{{$isoTimestamp}}",
2930
+ "forLineage" : false,
2931
+ "forDuplicateProcessing" : false
2932
+ }
2933
+
2934
+ """
2935
+
2936
+ url = (f"{self.external_reference_command_root}/{external_reference_guid}/members/"
2937
+ f"{element_guid}/detach")
2938
+ await self._async_delete_request(url, body)
2939
+ logger.info(f"Removed member {element_guid} from external_reference {external_reference_guid}")
2940
+
2941
+
2942
+ def remove_from_external_reference(self, external_reference_guid: str, element_guid: str,
2943
+ body: dict | DeleteRequestBody= None) -> None:
2944
+ """Remove an element from a external_reference. Async version.
2945
+
2946
+ Parameters
2947
+ ----------
2948
+ external_reference_guid: str
2949
+ identity of the external_reference to return members for.
2950
+ element_guid: str
2951
+ Effective time of the query. If not specified will default to any time.
2952
+ body: dict, optional, defaults to None
2953
+ The body of the request to add to the external_reference. See notes.
2954
+
2955
+ Returns
2956
+ -------
2957
+ None
2958
+
2959
+ Raises
2960
+ ------
2961
+
2962
+ InvalidParameterException
2963
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
2964
+ PropertyServerException
2965
+ Raised by the server when an issue arises in processing a valid request
2966
+ NotAuthorizedException
2967
+ The principle specified by the user_id does not have authorization for the requested action
2968
+
2969
+ Notes
2970
+ -----
2971
+ {
2972
+ "class" : "MetadataSourceRequestBody",
2973
+ "externalSourceGUID": "add guid here",
2974
+ "externalSourceName": "add qualified name here",
2975
+ "effectiveTime" : "{{$isoTimestamp}}",
2976
+ "forLineage" : false,
2977
+ "forDuplicateProcessing" : false
2978
+ }
2979
+
2980
+ """
2981
+ loop = asyncio.get_event_loop()
2982
+ loop.run_until_complete(self._async_remove_from_external_reference(external_reference_guid, element_guid, body))
2983
+
2984
+ #
2985
+ #
2986
+ #
2987
+
2988
+
2989
+ def remove_term_from_category(self, folder_guid: str, term_guid: str,
2990
+ body: dict | DeleteRequestBody= None) -> None:
2991
+ """Remove a term from a category.
2992
+
2993
+ Parameters
2994
+ ----------
2995
+ category_guid: str
2996
+ identity of the external_reference to return members for.
2997
+ term_guid: str
2998
+ Effective time of the query. If not specified will default to any time.
2999
+ body: dict, optional, defaults to None
3000
+ The body of the request to add to the external_reference. See notes.
3001
+
3002
+ Returns
3003
+ -------
3004
+ None
3005
+
3006
+ Raises
3007
+ ------
3008
+
3009
+ InvalidParameterException
3010
+ If the client passes incorrect parameters on the request - such as bad URLs or invalid values
3011
+ PropertyServerException
3012
+ Raised by the server when an issue arises in processing a valid request
3013
+ NotAuthorizedException
3014
+ The principle specified by the user_id does not have authorization for the requested action
3015
+
3016
+ Notes
3017
+ -----
3018
+
3019
+ """
3020
+ loop = asyncio.get_event_loop()
3021
+ loop.run_until_complete(self._async_remove_from_external_reference(folder_guid, term_guid, body))
3022
+
3023
+ #
3024
+ #
3025
+ #
3026
+
3027
+
3028
+ @dynamic_catch
3029
+ async def _async_get_member_list(self, external_reference_guid: str = None, external_reference_name: str = None,
3030
+ external_reference_qname: str = None, ) -> list | str:
3031
+ """Get the member list for the external_reference - async version.
3032
+ Parameters
3033
+ ----------
3034
+ external_reference_guid: str,
3035
+ identity of the external_reference to return members for. If none, external_reference_name or
3036
+ external_reference_qname are used.
3037
+ external_reference_name: str,
3038
+ display name of the external_reference to return members for. If none, external_reference_guid
3039
+ or external_reference_qname are used.
3040
+ external_reference_qname: str,
3041
+ qualified name of the external_reference to return members for. If none, external_reference_guid
3042
+ or external_reference_name are used.
3043
+
3044
+ Returns
3045
+ -------
3046
+ list | str
3047
+ The list of member information if successful, otherwise the string "No members found"
3048
+
3049
+ Raises
3050
+ ------
3051
+ InvalidParameterException
3052
+ If the root_external_reference_name does not have exactly one root external_reference.
3053
+
3054
+ """
3055
+
3056
+ # first find the guid for the external_reference we are using as root
3057
+
3058
+ # now find the members of the external_reference
3059
+ member_list = []
3060
+ members = await self._async_get_external_reference_members(external_reference_guid, external_reference_name, external_reference_qname)
3061
+ if (type(members) is str) or (len(members) == 0):
3062
+ logger.trace(f"No members found for external_reference {external_reference_guid}")
3063
+ return "No members found"
3064
+ # finally, construct a list of member information
3065
+ for member_rel in members:
3066
+ member_guid = member_rel["elementHeader"]["guid"]
3067
+ member = await self._async_get_element_by_guid_(member_guid)
3068
+ if isinstance(member, dict):
3069
+ member_instance = {
3070
+ "name": member["properties"].get('displayName', ''),
3071
+ "qualifiedName": member["properties"]["qualifiedName"], "guid": member["elementHeader"]["guid"],
3072
+ "description": member["properties"].get("description", ''),
3073
+ "type": member["elementHeader"]["type"]['typeName'],
3074
+ }
3075
+ member_list.append(member_instance)
3076
+ logger.debug(f"Member list for external_reference {external_reference_guid}: {member_list}")
3077
+ return member_list if len(member_list) > 0 else "No members found"
3078
+
3079
+
3080
+ def get_member_list(self, external_reference_guid: str = None, external_reference_name: str = None,
3081
+ external_reference_qname: str = None, ) -> list | bool:
3082
+ """Get the member list for a external_reference - async version.
3083
+ Parameters
3084
+ ----------
3085
+ external_reference_guid: str,
3086
+ identity of the external_reference to return members for. If none, external_reference_name or
3087
+ external_reference_qname are used.
3088
+ external_reference_name: str,
3089
+ display name of the external_reference to return members for. If none, external_reference_guid
3090
+ or external_reference_qname are used.
3091
+ external_reference_qname: str,
3092
+ qualified name of the external_reference to return members for. If none, external_reference_guid
3093
+ or external_reference_name are used.
3094
+ Returns
3095
+ -------
3096
+ list | bool
3097
+ The list of member information if successful, otherwise False.
3098
+
3099
+ Raises
3100
+ ------
3101
+ InvalidParameterException
3102
+ If the root_external_reference_name does not have exactly one root external_reference.
3103
+
3104
+ """
3105
+ loop = asyncio.get_event_loop()
3106
+ resp = loop.run_until_complete(
3107
+ self._async_get_member_list(external_reference_guid, external_reference_name, external_reference_qname))
3108
+ return resp
3109
+
3110
+ def _extract_digital_product_properties(self, element: dict, guid: str, output_format: str) -> dict:
3111
+ props = element["properties"]
3112
+ digital_prod = DigitalProductProperties.model_validate(props)
3113
+ added_props = get_defined_field_values(digital_prod)
3114
+
3115
+ used_by_digital_products = element.get("usedByDigitalProducts", "")
3116
+ if isinstance(used_by_digital_products, (list | dict)):
3117
+ used_by_digital_products_list = ""
3118
+ for prod in used_by_digital_products:
3119
+ used_by_digital_products_list += f"{prod["relatedElement"]["properties"]["qualifiedName"]}, "
3120
+ added_props["used_by_digital_products"] = used_by_digital_products_list[:-2]
3121
+
3122
+ uses_digital_products = element.get("usesDigitalProducts", "")
3123
+ if isinstance(uses_digital_products, (list | dict)):
3124
+ uses_digital_products_list = ""
3125
+ for prod in uses_digital_products:
3126
+ uses_digital_products_list += f"{prod["relatedElement"]["properties"]["qualifiedName"]}, "
3127
+ added_props["uses_digital_products"] = uses_digital_products_list[:-2]
3128
+
3129
+ return added_props
3130
+
3131
+ def _extract_agreement_properties(self, element: dict, guid: str, output_format: str) -> dict:
3132
+ props = element["properties"]
3133
+ # agreement = Collections.model_validate(props)
3134
+ # added_props = get_defined_field_values(agreement)
3135
+
3136
+ added_props = {}
3137
+ agreement_items = element.get("agreementItems", "")
3138
+ if isinstance(agreement_items, (list | dict)):
3139
+ agreement_items_list = ""
3140
+ for item in agreement_items:
3141
+ agreement_items_list += f"{item["relatedElement"]["properties"]["qualifiedName"]}, "
3142
+ added_props["agreementItems"] = agreement_items_list[:-2]
3143
+
3144
+ return added_props
3145
+
3146
+ def _extract_external_reference_properties(self, element: dict, columns_struct: dict) -> dict:
3147
+ """
3148
+ Extract common properties from a external_reference element and populate into the provided columns_struct.
3149
+
3150
+ Args:
3151
+ element (dict): The external_reference element
3152
+ columns_struct (dict): The columns structure to populate
3153
+
3154
+ Returns:
3155
+ dict: columns_struct with column 'value' fields populated
3156
+ """
3157
+ # First, populate from element.properties using the utility
3158
+ col_data = populate_columns_from_properties(element, columns_struct)
3159
+
3160
+ columns_list = col_data.get("formats", {}).get("columns", [])
3161
+
3162
+ # Populate header-derived values
3163
+ header_props = _extract_referenceable_properties(element)
3164
+ for column in columns_list:
3165
+ key = column.get('key')
3166
+ if key in header_props:
3167
+ column['value'] = header_props.get(key)
3168
+ elif isinstance(key, str) and key.lower() == 'guid':
3169
+ column['value'] = header_props.get('GUID')
3170
+
3171
+ # Derived/computed fields
3172
+ # external_referenceCategories are classifications
3173
+ classification_names = ""
3174
+ classifications = element.get('elementHeader', {}).get("external_referenceCategories", [])
3175
+ for classification in classifications:
3176
+ classification_names += f"{classification['classificationName']}, "
3177
+ if classification_names:
3178
+ for column in columns_list:
3179
+ if column.get('key') == 'classifications':
3180
+ column['value'] = classification_names[:-2]
3181
+ break
3182
+
3183
+ # Populate requested relationship-based columns generically from top-level keys
3184
+ col_data = get_required_relationships(element, col_data)
3185
+
3186
+ # Subject area classification
3187
+ subject_area = element.get('elementHeader', {}).get("subjectArea", "") or ""
3188
+ subj_val = ""
3189
+ if isinstance(subject_area, dict):
3190
+ subj_val = subject_area.get("classificationProperties", {}).get("subjectAreaName", "")
3191
+ for column in columns_list:
3192
+ if column.get('key') == 'subject_area':
3193
+ column['value'] = subj_val
3194
+ break
3195
+
3196
+ # Mermaid graph
3197
+ mermaid_val = element.get('mermaidGraph', "") or ""
3198
+ for column in columns_list:
3199
+ if column.get('key') == 'mermaid':
3200
+ column['value'] = mermaid_val
3201
+ break
3202
+
3203
+ logger.trace(f"Extracted/Populated columns: {col_data}")
3204
+
3205
+ return col_data
3206
+
3207
+
3208
+ def _generate_external_reference_output(self, elements: dict|list[dict], filter: Optional[str],
3209
+ element_type_name: Optional[str], output_format: str = "DICT",
3210
+ output_format_set: dict | str = None) -> str| list[dict]:
3211
+ """ Generate output for external_references in the specified format.
3212
+
3213
+ Args:
3214
+ elements (Union[Dict, List[Dict]]): Dictionary or list of dictionaries containing data field elements
3215
+ filter (Optional[str]): The search string used to find the elements
3216
+ element_type_name (Optional[str]): The type of external_reference
3217
+ output_format (str): The desired output format (MD, FORM, REPORT, LIST, DICT, MERMAID, HTML)
3218
+ output_format_set (Optional[dict], optional): List of dictionaries containing column data. Defaults
3219
+ to None.
3220
+
3221
+ Returns:
3222
+ Union[str, List[Dict]]: Formatted output as a string or list of dictionaries
3223
+ """
3224
+ if element_type_name is None:
3225
+ entity_type = "Collections"
3226
+ else:
3227
+ entity_type = element_type_name
3228
+ # First see if the user has specified an output_format_set - either a label or a dict
3229
+ get_additional_props_func = None
3230
+ if output_format_set:
3231
+ if isinstance(output_format_set, str):
3232
+ output_formats = select_output_format_set(output_format_set, output_format)
3233
+ elif isinstance(output_format_set, dict):
3234
+ output_formats = get_output_format_type_match(output_format_set, output_format)
3235
+
3236
+ # If no output_format was set, then use the element_type_name to lookup the output format
3237
+ elif element_type_name:
3238
+ output_formats = select_output_format_set(element_type_name, output_format)
3239
+ else:
3240
+ # fallback to external_references or entity type
3241
+ output_formats = select_output_format_set(entity_type,output_format)
3242
+ if output_formats is None:
3243
+ output_formats = select_output_format_set("Default", output_format)
3244
+
3245
+ if output_formats:
3246
+ get_additional_props_name = output_formats.get("get_additional_props", {}).get("function", None)
3247
+ if isinstance(get_additional_props_name, str):
3248
+ class_name, method_name = get_additional_props_name.split(".")
3249
+ if hasattr(self, method_name):
3250
+ get_additional_props_func = getattr(self, method_name)
3251
+
3252
+ logger.trace(f"Executing generate_external_reference_output for {entity_type}: {output_formats}")
3253
+ return generate_output(
3254
+ elements,
3255
+ filter,
3256
+ entity_type,
3257
+ output_format,
3258
+ self._extract_external_reference_properties,
3259
+ get_additional_props_func,
3260
+ output_formats,
3261
+ )
3262
+
3263
+
3264
+ from typing import Union, Dict, List, Optional
3265
+
3266
+ if __name__ == "__main__":
3267
+ print("Main-Collection Manager")