Skip to content

Commit edbcb71

Browse files
authored
Merge pull request #39 from atlanhq/change_custom_metadata
Made changes to updating custom meta data
2 parents f363382 + 325242b commit edbcb71

10 files changed

Lines changed: 340 additions & 54 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ wheels/
5050
.installed.cfg
5151
*.egg
5252
*.DS_Store
53+
examples/

pyatlan/cache/custom_metadata_cache.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# SPDX-License-Identifier: Apache-2.0
22
# Copyright 2022 Atlan Pte. Ltd.
33
import json
4-
from typing import Optional
4+
from typing import Any, Optional
55

66
from pyatlan.client.atlan import AtlanClient
77
from pyatlan.error import LogicError, NotFoundError
8+
from pyatlan.model.core import CustomMetadata
89
from pyatlan.model.enums import AtlanTypeCategory
910
from pyatlan.model.typedef import AttributeDef, CustomMetadataDef
1011

@@ -35,7 +36,7 @@ class CustomMetadataCache:
3536

3637
@classmethod
3738
def _refresh_cache(cls) -> None:
38-
from pyatlan.model.core import BusinessAttributes, to_snake_case
39+
from pyatlan.model.core import CustomMetadata, to_snake_case
3940

4041
client = AtlanClient.get_default_client()
4142
if client is None:
@@ -58,7 +59,7 @@ def _refresh_cache(cls) -> None:
5859
cls.map_attr_name_to_id[type_id] = {}
5960
meta_name = cm.display_name.replace(" ", "")
6061
attribute_class_name = f"Attributes_{meta_name}"
61-
attrib_type = type(attribute_class_name, (BusinessAttributes,), {})
62+
attrib_type = type(attribute_class_name, (CustomMetadata,), {})
6263
attrib_type._meta_data_type_id = type_id # type: ignore
6364
attrib_type._meta_data_type_name = type_name # type: ignore
6465
cls.map_id_to_type[type_id] = attrib_type
@@ -202,3 +203,30 @@ def get_attributes_for_search_results(cls, set_name: str) -> Optional[list[str]]
202203
cls._refresh_cache()
203204
return cls._get_attributes_for_search_results(set_id)
204205
return None
206+
207+
@classmethod
208+
def get_custom_metadata(
209+
cls,
210+
name: str,
211+
asset_type: type,
212+
business_attributes: Optional[dict[str, Any]] = None,
213+
) -> CustomMetadata:
214+
type_name = asset_type.__name__
215+
ba_id = cls.get_id_for_name(name)
216+
if ba_id is None:
217+
raise ValueError(f"No custom metadata with the name: {name} exist")
218+
for a_type in CustomMetadataCache.types_by_asset[type_name]:
219+
if (
220+
hasattr(a_type, "_meta_data_type_name")
221+
and a_type._meta_data_type_name == name
222+
):
223+
break
224+
else:
225+
raise ValueError(f"Custom metadata {name} is not applicable to {type_name}")
226+
if ba_type := CustomMetadataCache.get_type_for_id(ba_id):
227+
return (
228+
ba_type(business_attributes[ba_id])
229+
if business_attributes and ba_id in business_attributes
230+
else ba_type()
231+
)
232+
raise ValueError(f"Custom metadata {name} is not applicable to {type_name}")

pyatlan/client/atlan.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from urllib3.util.retry import Retry
2121

2222
from pyatlan.client.constants import (
23+
ADD_BUSINESS_ATTRIBUTE_BY_ID,
2324
BULK_UPDATE,
2425
CREATE_TYPE_DEFS,
2526
DELETE_ENTITY_BY_ATTRIBUTE,
@@ -57,6 +58,8 @@
5758
Classification,
5859
ClassificationName,
5960
Classifications,
61+
CustomMetadata,
62+
CustomMetadataReqest,
6063
)
6164
from pyatlan.model.enums import AtlanDeleteType, AtlanTypeCategory, CertificateStatus
6265
from pyatlan.model.response import AssetMutationResponse
@@ -377,11 +380,12 @@ def upsert(
377380
entity: Union[Asset, list[Asset]],
378381
replace_classifications: bool = False,
379382
replace_custom_metadata: bool = False,
383+
overwrite_custom_metadata: bool = False,
380384
) -> AssetMutationResponse:
381385
query_params = {
382386
"replaceClassifications": replace_classifications,
383387
"replaceBusinessAttributes": replace_custom_metadata,
384-
"overwriteBusinessAttribute": replace_custom_metadata,
388+
"overwriteBusinessAttributes": overwrite_custom_metadata,
385389
}
386390
entities: list[Asset] = []
387391
if isinstance(entity, list):
@@ -587,3 +591,14 @@ def remove_announcement(
587591
asset.name = name
588592
asset.remove_announcement()
589593
return self._update_asset_by_attribute(asset, asset_type, qualified_name)
594+
595+
def replace_custom_metadata(self, guid: str, custom_metadata: CustomMetadata):
596+
# TODO: This endpoint is not currently functioning correctly on the server
597+
custom_metadata_request = CustomMetadataReqest(__root__=custom_metadata)
598+
self._call_api(
599+
ADD_BUSINESS_ATTRIBUTE_BY_ID.format_path(
600+
{"entity_guid": guid, "bm_id": custom_metadata._meta_data_type_id}
601+
),
602+
None,
603+
custom_metadata_request,
604+
)

pyatlan/client/constants.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@
122122

123123
# Business Attributes APIs
124124
ADD_BUSINESS_ATTRIBUTE = API(
125-
ENTITY_API + "guid/{entity_guid}/businessmetadata",
125+
ENTITY_API + "guid/{entity_guid}/businessmetadata/",
126+
HTTPMethod.POST,
127+
HTTPStatus.NO_CONTENT,
128+
)
129+
ADD_BUSINESS_ATTRIBUTE_BY_ID = API(
130+
ENTITY_API + "guid/{entity_guid}/businessmetadata/{bm_id}",
126131
HTTPMethod.POST,
127132
HTTPStatus.NO_CONTENT,
128133
)

pyatlan/generator/templates/entity.jinja2

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ from typing import Any, ClassVar, Dict, List, Optional, TypeVar
99

1010
from pydantic import Field, StrictStr, root_validator, validator
1111

12-
from pyatlan.model.core import Announcement, AtlanObject, BusinessAttributes, Classification, Meaning
12+
from pyatlan.model.core import Announcement, AtlanObject, CustomMetadata, Classification, Meaning
1313
from pyatlan.model.enums import (
1414
ADLSAccessTier,
1515
ADLSAccountStatus,
@@ -226,7 +226,7 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
226226
if not self.create_time or self.created_by:
227227
self.attributes.validate_required()
228228

229-
def get_business_attributes(self, name: str) -> BusinessAttributes:
229+
def get_custom_metadata(self, name: str) -> CustomMetadata:
230230
from pyatlan.cache.custom_metadata_cache import CustomMetadataCache
231231

232232
ba_id = CustomMetadataCache.get_id_for_name(name)
@@ -240,7 +240,7 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
240240
break
241241
else:
242242
raise ValueError(
243-
f"Business attributes {name} are not applicable to {self.type_name}"
243+
f"Custom metadata attributes {name} are not applicable to {self.type_name}"
244244
)
245245
if ba_type := CustomMetadataCache.get_type_for_id(ba_id):
246246
return (
@@ -250,27 +250,27 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
250250
)
251251
else:
252252
raise ValueError(
253-
f"Business attributes {name} are not applicable to {self.type_name}"
253+
f"Custom metadata attributes {name} are not applicable to {self.type_name}"
254254
)
255255

256-
def set_business_attribute(self, business_attributes: BusinessAttributes) -> None:
256+
def set_custom_metadata(self, custom_metadata: CustomMetadata) -> None:
257257
from pyatlan.cache.custom_metadata_cache import CustomMetadataCache
258258

259-
if not isinstance(business_attributes, BusinessAttributes):
259+
if not isinstance(custom_metadata, CustomMetadata):
260260
raise ValueError(
261-
"business_attributes must be an instance of BusinessAttributes"
261+
"business_attributes must be an instance of CustomMetadata"
262262
)
263263
if (
264-
type(business_attributes)
264+
type(custom_metadata)
265265
not in CustomMetadataCache.types_by_asset[self.type_name]
266266
):
267267
raise ValueError(
268-
f"Business attributes {business_attributes._meta_data_type_name} are not applicable to {self.type_name}"
268+
f"Business attributes {custom_metadata._meta_data_type_name} are not applicable to {self.type_name}"
269269
)
270-
ba_dict = dict(business_attributes)
270+
ba_dict = dict(custom_metadata)
271271
if not self.business_attributes:
272272
self.business_attributes = {}
273-
self.business_attributes[business_attributes._meta_data_type_id] = ba_dict
273+
self.business_attributes[custom_metadata._meta_data_type_id] = ba_dict
274274

275275
{%- else %}
276276
{%- if entity_def.name == "Asset" %}
@@ -536,7 +536,7 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
536536
)
537537
else:
538538
raise ValueError(
539-
f"parent_type must be either Table, View or MaterializeView"
539+
"parent_type must be either Table, View or MaterializeView"
540540
)
541541
return ret_value
542542

0 commit comments

Comments
 (0)