Skip to content

Commit 6e39433

Browse files
committed
Add create method to BadgeCondition
1 parent ee73c28 commit 6e39433

10 files changed

Lines changed: 450 additions & 262 deletions

File tree

pyatlan/cache/custom_metadata_cache.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def refresh_cache(cls) -> None:
9191
cls.types_by_asset[asset_type].add(attrib_type)
9292

9393
@classmethod
94-
def get_id_for_name(cls, name: str) -> Optional[str]:
94+
def get_id_for_name(cls, name: str) -> str:
9595
"""
9696
Translate the provided human-readable custom metadata set name to its Atlan-internal ID string.
9797
"""
@@ -113,7 +113,7 @@ def get_id_for_name(cls, name: str) -> Optional[str]:
113113
)
114114

115115
@classmethod
116-
def get_name_for_id(cls, idstr: str) -> Optional[str]:
116+
def get_name_for_id(cls, idstr: str) -> str:
117117
"""
118118
Translate the provided Atlan-internal custom metadata ID string to the human-readable custom metadata set name.
119119
"""
@@ -174,23 +174,32 @@ def get_all_custom_attributes(
174174
return m
175175

176176
@classmethod
177-
def get_attr_id_for_name(cls, set_name: str, attr_name: str) -> Optional[str]:
177+
def get_attr_id_for_name(cls, set_name: str, attr_name: str) -> str:
178178
"""
179179
Translate the provided human-readable custom metadata set and attribute names to the Atlan-internal ID string
180180
for the attribute.
181181
"""
182-
attr_id = None
183-
if set_id := cls.get_id_for_name(set_name):
184-
if sub_map := cls.map_attr_name_to_id.get(set_id):
185-
attr_id = sub_map.get(attr_name)
182+
set_id = cls.get_id_for_name(set_name)
183+
if sub_map := cls.map_attr_name_to_id.get(set_id):
184+
attr_id = sub_map.get(attr_name)
186185
if attr_id:
187186
# If found, return straight away
188187
return attr_id
189-
# Otherwise, refresh the cache and look again (could be stale)
190-
cls.refresh_cache()
191-
if sub_map := cls.map_attr_name_to_id.get(set_id):
192-
return sub_map.get(attr_name)
193-
return None
188+
# Otherwise, refresh the cache and look again (could be stale)
189+
cls.refresh_cache()
190+
if sub_map := cls.map_attr_name_to_id.get(set_id):
191+
attr_id = sub_map.get(attr_name)
192+
if attr_id:
193+
# If found, return straight away
194+
return attr_id
195+
raise NotFoundError(
196+
message=f"Custom metadata property with name {attr_name} does not exist in custom metadata {set_name}.",
197+
code="ATLAN-PYTHON-404-009",
198+
)
199+
raise NotFoundError(
200+
message=f"Custom metadata with ID {set_id} does not exist.",
201+
code="ATLAN-PYTHON-404-009",
202+
)
194203

195204
@classmethod
196205
def get_attr_name_for_id(cls, set_id: str, attr_id: str) -> Optional[str]:
@@ -199,8 +208,7 @@ def get_attr_name_for_id(cls, set_id: str, attr_id: str) -> Optional[str]:
199208
for the attribute.
200209
"""
201210
if sub_map := cls.map_attr_id_to_name.get(set_id):
202-
attr_name = sub_map.get(attr_id)
203-
if attr_name:
211+
if attr_name := sub_map.get(attr_id):
204212
return attr_name
205213
cls.refresh_cache()
206214
if sub_map := cls.map_attr_id_to_name.get(set_id):

pyatlan/generator/templates/entity.jinja2

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ from typing import Any, ClassVar, Dict, List, Optional, TypeVar
1111

1212
from pydantic import Field, StrictStr, root_validator, validator
1313

14-
from pyatlan.model.core import Announcement, AtlanObject, CustomMetadata, Classification, Meaning
14+
from pyatlan.model.core import (
15+
Announcement,
16+
AtlanObject,
17+
CustomMetadata,
18+
Classification,
19+
Meaning,
20+
)
1521
from pyatlan.model.enums import (
1622
ADLSAccessTier,
1723
ADLSAccountStatus,
@@ -37,7 +43,7 @@ from pyatlan.model.enums import (
3743
QueryUsernameStrategy,
3844
SourceCostUnitType,
3945
GoogleDatastudioAssetType,
40-
PowerbiEndorsement
46+
PowerbiEndorsement,
4147
)
4248
from pyatlan.model.internal import AtlasServer, Internal
4349
from pyatlan.model.structs import (
@@ -55,9 +61,10 @@ from pyatlan.model.structs import (
5561
PopularityInsights,
5662
SourceTagAttribute,
5763
)
58-
from pyatlan.utils import next_id
64+
from pyatlan.utils import next_id, validate_required_fields
5965
from urllib.parse import quote, unquote
6066

67+
6168
def validate_single_required_field(field_names: list[str], values: list[Any]):
6269
indexes = [idx for idx, value in enumerate(values) if value is not None]
6370
if not indexes:
@@ -70,39 +77,8 @@ def validate_single_required_field(field_names: list[str], values: list[Any]):
7077
f"Only one of the following parameters are allowed: {', '.join(names)}"
7178
)
7279

73-
def validate_required_fields(field_names: list[str], values: list[Any]):
74-
for field_name, value in zip(field_names, values):
75-
if value is None:
76-
raise ValueError(f"{field_name} is required")
77-
if isinstance(value, str) and not value.strip():
78-
raise ValueError(f"{field_name} cannot be blank")
79-
if isinstance(value, list) and len(value) == 0:
80-
raise ValueError(f"{field_name} cannot be an empty list")
81-
{%- macro gen_properties(attribute_defs, additional_names=[]) %}
82-
_convience_properties: ClassVar[list[str]] = [
83-
{%- for attribute_def in attribute_defs %}
84-
"{{ attribute_def.name | to_snake_case }}",
85-
{%- endfor %}
86-
{%- for name in additional_names %}
87-
"{{ name }}",
88-
{%- endfor %}]
89-
90-
{%- for attribute_def in attribute_defs %}
91-
{%- set type = attribute_def.typeName | get_type %}
92-
{%- set property_type %}{% if attribute_def.isOptional %}Optional[{% endif %}{{type}}{% if attribute_def.isOptional %}]{% endif %}{% endset %}
93-
{%- set property_name = attribute_def.name | to_snake_case %}
94-
@property
95-
def {{ property_name }}(self)->{{ property_type }}:
96-
return self.attributes.{{ property_name }}
97-
98-
@{{ property_name }}.setter
99-
def {{ property_name }}(self, {{ property_name }}:{{ property_type }}):
100-
if self.attributes is None:
101-
self.attributes = self.Attributes()
102-
self.attributes.{{ property_name }} = {{ property_name }}
10380

104-
{%- endfor %}
105-
{% endmacro %}
81+
{% from 'macros.jinja2' import gen_properties %}
10682
SelfAsset = TypeVar("SelfAsset", bound="Asset")
10783
{% for entity_def in entity_defs %}
10884
{%- set super_classes = ['AtlanObject'] if not entity_def.super_types else entity_def.super_types -%}
@@ -367,11 +343,20 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
367343
{%- if entity_def.name == "Badge" %}
368344
@classmethod
369345
# @validate_arguments()
370-
def create(cls, *, name: StrictStr, cm_name: str, cm_attribute: str) -> Badge:
371-
validate_required_fields(["name", "cm_name", "cm_attribute"], [name])
346+
def create(
347+
cls,
348+
*,
349+
name: StrictStr,
350+
cm_name: str,
351+
cm_attribute: str,
352+
badge_conditions: list[BadgeCondition],
353+
) -> Badge:
372354
return cls(
373355
attributes=Badge.Attributes.create(
374-
name=name, cm_name=cm_name, cm_attribute=cm_attribute
356+
name=name,
357+
cm_name=cm_name,
358+
cm_attribute=cm_attribute,
359+
badge_conditions=badge_conditions,
375360
)
376361
)
377362
{%- elif entity_def.name == "Readme" %}
@@ -540,10 +525,16 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
540525
@classmethod
541526
# @validate_arguments()
542527
def create(
543-
cls, *, name: StrictStr, cm_name: str, cm_attribute: str
528+
cls,
529+
*,
530+
name: StrictStr,
531+
cm_name: str,
532+
cm_attribute: str,
533+
badge_conditions: list[BadgeCondition],
544534
) -> Badge.Attributes:
545535
validate_required_fields(
546-
["name", "cm_name", "cm_attribute"], [name, cm_name, cm_attribute]
536+
["name", "cm_name", "cm_attribute", "badge_conditions"],
537+
[name, cm_name, cm_attribute, badge_conditions],
547538
)
548539
from pyatlan.cache.custom_metadata_cache import CustomMetadataCache
549540

@@ -555,6 +546,7 @@ class {{ entity_def.name }}({{super_classes[0]}} {%- if "Asset" in super_classes
555546
name=name,
556547
qualified_name=f"badges/global/{cm_id}.{cm_attr_id}",
557548
badge_metadata_attribute=f"{cm_id}.{cm_attr_id}",
549+
badge_conditions=badge_conditions,
558550
)
559551
{%- elif entity_def.name == "Readme" %}
560552
@classmethod
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{%- macro gen_properties(attribute_defs, additional_names=[]) %}
2+
_convience_properties: ClassVar[list[str]] = [
3+
{%- for attribute_def in attribute_defs %}
4+
"{{ attribute_def.name | to_snake_case }}",
5+
{%- endfor %}
6+
{%- for name in additional_names %}
7+
"{{ name }}",
8+
{%- endfor %}]
9+
10+
{%- for attribute_def in attribute_defs %}
11+
{%- set type = attribute_def.typeName | get_type %}
12+
{%- set property_type %}{% if attribute_def.isOptional %}Optional[{% endif %}{{type}}{% if attribute_def.isOptional %}]{% endif %}{% endset %}
13+
{%- set property_name = attribute_def.name | to_snake_case %}
14+
@property
15+
def {{ property_name }}(self)->{{ property_type }}:
16+
return self.attributes.{{ property_name }}
17+
18+
@{{ property_name }}.setter
19+
def {{ property_name }}(self, {{ property_name }}:{{ property_type }}):
20+
if self.attributes is None:
21+
self.attributes = self.Attributes()
22+
self.attributes.{{ property_name }} = {{ property_name }}
23+
24+
{%- endfor %}
25+
{% endmacro %}
Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,48 @@
1-
# SPDX-License-Identifier: Apache-2.0
21
# Copyright 2022 Atlan Pte. Ltd.
32
from datetime import datetime
4-
from typing import Optional
3+
from typing import Optional, Union
54

65
from pydantic import Field
76

7+
from pyatlan.utils import validate_required_fields
88
from pyatlan.model.core import AtlanObject
9-
from pyatlan.model.enums import SourceCostUnitType
9+
from pyatlan.model.enums import (
10+
BadgeConditionColor,
11+
BadgeComparisonOperator,
12+
SourceCostUnitType,
13+
)
1014

1115
{% for struct in struct_defs %}
1216
class {{struct.name}}(AtlanObject):
1317
"""Description"""
14-
class Attributes(AtlanObject):
15-
{%- for attribute_def in struct.attribute_defs %}
16-
{%- set type = attribute_def.type_name | get_type %}
17-
{{attribute_def.name | to_snake_case }}: {% if attribute_def.is_optional %}Optional[{% endif %}{{type}}{% if attribute_def.is_optional %}]{% endif %} = Field(None, description='' , alias='{{attribute_def.name}}')
18-
{%- endfor %}
18+
{%- if struct.name == "BadgeCondition" %}
19+
@classmethod
20+
# @validate_arguments()
21+
def create(
22+
cls,
23+
*,
24+
badge_condition_operator: BadgeComparisonOperator,
25+
badge_condition_value: str,
26+
badge_condition_colorhex: Union[BadgeConditionColor, str]
27+
) -> "BadgeCondition":
28+
validate_required_fields(
29+
[
30+
"badge_condition_operator",
31+
"badge_condition_value",
32+
"badge_condition_colorhex",
33+
],
34+
[badge_condition_operator, badge_condition_value, badge_condition_colorhex],
35+
)
36+
return cls(
37+
badge_condition_operator=badge_condition_operator.value,
38+
badge_condition_value=badge_condition_value,
39+
badge_condition_colorhex=badge_condition_colorhex.value
40+
if isinstance(badge_condition_colorhex, BadgeConditionColor)
41+
else badge_condition_colorhex,
42+
)
43+
{% endif %}
44+
{%- for attribute_def in struct.attribute_defs %}
45+
{%- set type = attribute_def.type_name | get_type %}
46+
{{attribute_def.name | to_snake_case }}: {% if attribute_def.is_optional %}Optional[{% endif %}{{type}}{% if attribute_def.is_optional %}]{% endif %} = Field(None, description='' , alias='{{attribute_def.name}}')
47+
{%- endfor %}
1948
{% endfor %}

pyatlan/model/assets.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
PopularityInsights,
6363
SourceTagAttribute,
6464
)
65-
from pyatlan.utils import next_id
65+
from pyatlan.utils import next_id, validate_required_fields
6666

6767

6868
def validate_single_required_field(field_names: list[str], values: list[Any]):
@@ -78,16 +78,6 @@ def validate_single_required_field(field_names: list[str], values: list[Any]):
7878
)
7979

8080

81-
def validate_required_fields(field_names: list[str], values: list[Any]):
82-
for field_name, value in zip(field_names, values):
83-
if value is None:
84-
raise ValueError(f"{field_name} is required")
85-
if isinstance(value, str) and not value.strip():
86-
raise ValueError(f"{field_name} cannot be blank")
87-
if isinstance(value, list) and len(value) == 0:
88-
raise ValueError(f"{field_name} cannot be an empty list")
89-
90-
9181
SelfAsset = TypeVar("SelfAsset", bound="Asset")
9282

9383

@@ -3630,11 +3620,20 @@ def validate_type_name(cls, v):
36303620

36313621
@classmethod
36323622
# @validate_arguments()
3633-
def create(cls, *, name: StrictStr, cm_name: str, cm_attribute: str) -> Badge:
3634-
validate_required_fields(["name", "cm_name", "cm_attribute"], [name])
3623+
def create(
3624+
cls,
3625+
*,
3626+
name: StrictStr,
3627+
cm_name: str,
3628+
cm_attribute: str,
3629+
badge_conditions: list[BadgeCondition],
3630+
) -> Badge:
36353631
return cls(
36363632
attributes=Badge.Attributes.create(
3637-
name=name, cm_name=cm_name, cm_attribute=cm_attribute
3633+
name=name,
3634+
cm_name=cm_name,
3635+
cm_attribute=cm_attribute,
3636+
badge_conditions=badge_conditions,
36383637
)
36393638
)
36403639

@@ -3667,10 +3666,16 @@ class Attributes(Asset.Attributes):
36673666
@classmethod
36683667
# @validate_arguments()
36693668
def create(
3670-
cls, *, name: StrictStr, cm_name: str, cm_attribute: str
3669+
cls,
3670+
*,
3671+
name: StrictStr,
3672+
cm_name: str,
3673+
cm_attribute: str,
3674+
badge_conditions: list[BadgeCondition],
36713675
) -> Badge.Attributes:
36723676
validate_required_fields(
3673-
["name", "cm_name", "cm_attribute"], [name, cm_name, cm_attribute]
3677+
["name", "cm_name", "cm_attribute", "badge_conditions"],
3678+
[name, cm_name, cm_attribute, badge_conditions],
36743679
)
36753680
from pyatlan.cache.custom_metadata_cache import CustomMetadataCache
36763681

@@ -3682,6 +3687,7 @@ def create(
36823687
name=name,
36833688
qualified_name=f"badges/global/{cm_id}.{cm_attr_id}",
36843689
badge_metadata_attribute=f"{cm_id}.{cm_attr_id}",
3690+
badge_conditions=badge_conditions,
36853691
)
36863692

36873693
attributes: "Badge.Attributes" = Field(

pyatlan/model/enums.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,19 @@ class LineageDirection(str, Enum):
262262
UPSTREAM = "INPUT"
263263
DOWNSTREAM = "OUTPUT"
264264
BOTH = "BOTH"
265+
266+
267+
class BadgeComparisonOperator(str, Enum):
268+
GT = "gt"
269+
GTE = "gte"
270+
LT = "lt"
271+
LTE = "lte"
272+
EQ = "eq"
273+
NEQ = "neq"
274+
275+
276+
class BadgeConditionColor(str, Enum):
277+
GREEN = "#047960"
278+
YELLOW = "#F7B43D"
279+
RED = "#BF1B1B"
280+
GREY = "#525C73"

0 commit comments

Comments
 (0)