@@ -313,8 +313,7 @@ def get_asset_by_qualified_name(
313
313
raw_json ["entity" ]["attributes" ].update (
314
314
raw_json ["entity" ]["relationshipAttributes" ]
315
315
)
316
- asset = AssetResponse [A ](** raw_json ).entity
317
- asset .is_incomplete = False
316
+ asset = self .handle_relationships (raw_json )
318
317
if not isinstance (asset , asset_type ):
319
318
raise NotFoundError (
320
319
message = f"Asset with qualifiedName { qualified_name } "
@@ -345,16 +344,7 @@ def get_asset_by_guid(
345
344
GET_ENTITY_BY_GUID .format_path_with_params (guid ),
346
345
query_params ,
347
346
)
348
- if (
349
- "relationshipAttributes" in raw_json ["entity" ]
350
- and raw_json ["entity" ]["relationshipAttributes" ]
351
- ):
352
- raw_json ["entity" ]["attributes" ].update (
353
- raw_json ["entity" ]["relationshipAttributes" ]
354
- )
355
- raw_json ["entity" ]["relationshipAttributes" ] = {}
356
- asset = AssetResponse [A ](** raw_json ).entity
357
- asset .is_incomplete = False
347
+ asset = self .handle_relationships (raw_json )
358
348
if not isinstance (asset , asset_type ):
359
349
raise NotFoundError (
360
350
message = f"Asset with GUID { guid } is not of the type requested: { asset_type .__name__ } ." ,
@@ -366,6 +356,19 @@ def get_asset_by_guid(
366
356
raise NotFoundError (message = ae .user_message , code = ae .code ) from ae
367
357
raise ae
368
358
359
+ def handle_relationships (self , raw_json ):
360
+ if (
361
+ "relationshipAttributes" in raw_json ["entity" ]
362
+ and raw_json ["entity" ]["relationshipAttributes" ]
363
+ ):
364
+ raw_json ["entity" ]["attributes" ].update (
365
+ raw_json ["entity" ]["relationshipAttributes" ]
366
+ )
367
+ raw_json ["entity" ]["relationshipAttributes" ] = {}
368
+ asset = AssetResponse [A ](** raw_json ).entity
369
+ asset .is_incomplete = False
370
+ return asset
371
+
369
372
@validate_arguments ()
370
373
def retrieve_minimal (self , guid : str , asset_type : Type [A ]) -> A :
371
374
return self .get_asset_by_guid (
@@ -602,3 +605,100 @@ def replace_custom_metadata(self, guid: str, custom_metadata: CustomMetadata):
602
605
None ,
603
606
custom_metadata_request ,
604
607
)
608
+
609
+ @validate_arguments ()
610
+ def append_terms (
611
+ self ,
612
+ asset_type : Type [A ],
613
+ terms : list [AtlasGlossaryTerm ],
614
+ guid : Optional [str ] = None ,
615
+ qualified_name : Optional [str ] = None ,
616
+ ) -> A :
617
+ if guid :
618
+ if qualified_name :
619
+ raise ValueError (
620
+ "Either guid or qualified_name can be be specified not both"
621
+ )
622
+ asset = self .get_asset_by_guid (guid = guid , asset_type = asset_type )
623
+ elif qualified_name :
624
+ asset = self .get_asset_by_qualified_name (
625
+ qualified_name = qualified_name , asset_type = asset_type
626
+ )
627
+ else :
628
+ raise ValueError ("Either guid or qualified name must be specified" )
629
+ if not terms :
630
+ return asset
631
+ replacement_terms : list [AtlasGlossaryTerm ] = []
632
+ if existing_terms := asset .terms :
633
+ replacement_terms .extend (
634
+ term for term in existing_terms if term .relationship_status != "DELETED"
635
+ )
636
+ replacement_terms .extend (terms )
637
+ asset .terms = replacement_terms
638
+ response = self .upsert (entity = asset )
639
+ if assets := response .assets_updated (asset_type = asset_type ):
640
+ return assets [0 ]
641
+ return asset
642
+
643
+ @validate_arguments ()
644
+ def replace_terms (
645
+ self ,
646
+ asset_type : Type [A ],
647
+ terms : list [AtlasGlossaryTerm ],
648
+ guid : Optional [str ] = None ,
649
+ qualified_name : Optional [str ] = None ,
650
+ ) -> A :
651
+ if guid :
652
+ if qualified_name :
653
+ raise ValueError (
654
+ "Either guid or qualified_name can be be specified not both"
655
+ )
656
+ asset = self .get_asset_by_guid (guid = guid , asset_type = asset_type )
657
+ elif qualified_name :
658
+ asset = self .get_asset_by_qualified_name (
659
+ qualified_name = qualified_name , asset_type = asset_type
660
+ )
661
+ else :
662
+ raise ValueError ("Either guid or qualified name must be specified" )
663
+ asset .terms = terms
664
+ response = self .upsert (entity = asset )
665
+ if assets := response .assets_updated (asset_type = asset_type ):
666
+ return assets [0 ]
667
+ return asset
668
+
669
+ @validate_arguments ()
670
+ def remove_terms (
671
+ self ,
672
+ asset_type : Type [A ],
673
+ terms : list [AtlasGlossaryTerm ],
674
+ guid : Optional [str ] = None ,
675
+ qualified_name : Optional [str ] = None ,
676
+ ) -> A :
677
+ if not terms :
678
+ raise ValueError ("A list of terms to remove must be specified" )
679
+ if guid :
680
+ if qualified_name :
681
+ raise ValueError (
682
+ "Either guid or qualified_name can be be specified not both"
683
+ )
684
+ asset = self .get_asset_by_guid (guid = guid , asset_type = asset_type )
685
+ elif qualified_name :
686
+ asset = self .get_asset_by_qualified_name (
687
+ qualified_name = qualified_name , asset_type = asset_type
688
+ )
689
+ else :
690
+ raise ValueError ("Either guid or qualified name must be specified" )
691
+ replacement_terms : list [AtlasGlossaryTerm ] = []
692
+ guids_to_be_removed = {t .guid for t in terms }
693
+ if existing_terms := asset .terms :
694
+ replacement_terms .extend (
695
+ term
696
+ for term in existing_terms
697
+ if term .relationship_status != "DELETED"
698
+ and term .guid not in guids_to_be_removed
699
+ )
700
+ asset .terms = replacement_terms
701
+ response = self .upsert (entity = asset )
702
+ if assets := response .assets_updated (asset_type = asset_type ):
703
+ return assets [0 ]
704
+ return asset
0 commit comments