Skip to content

Commit 7b24d9a

Browse files
Aryamanz29claude
andcommitted
fix: give RICH_TEXT a distinct enum value so STRING and RICH_TEXT are not aliases
STRING and RICH_TEXT shared the same enum value ("string"), making them indistinguishable in Python's Enum. This caused STRING attributes to incorrectly get is_rich_text=True and RICH_TEXT multi-value restrictions to apply to STRING. Fixes PART-548 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 36b5900 commit 7b24d9a

4 files changed

Lines changed: 49 additions & 3 deletions

File tree

pyatlan/model/enums.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ class AtlanCustomAttributePrimitiveType(str, Enum):
402402
URL = "url"
403403
SQL = "SQL"
404404
LONG = "long"
405-
RICH_TEXT = "string"
405+
RICH_TEXT = "rich_text"
406406

407407

408408
class AtlanDeleteType(str, Enum):

pyatlan/model/typedef.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,16 @@ def create(
573573
[type],
574574
)
575575
# Explicitly set all defaults to ensure inclusion during pydantic serialization
576+
# RICH_TEXT has a distinct enum value but uses "string" as the
577+
# API-level primitive type, same as STRING.
578+
if attribute_type == AtlanCustomAttributePrimitiveType.RICH_TEXT:
579+
primitive_type = AtlanCustomAttributePrimitiveType.STRING.value
580+
else:
581+
primitive_type = attribute_type.value
582+
576583
options = AttributeDef.Options(
577584
custom_metadata_version="v2",
578-
primitive_type=attribute_type.value,
585+
primitive_type=primitive_type,
579586
applicable_entity_types='["Asset"]',
580587
allow_search=False,
581588
max_str_length="100000000",
@@ -978,6 +985,7 @@ def create(
978985
AtlanCustomAttributePrimitiveType.GROUPS,
979986
AtlanCustomAttributePrimitiveType.URL,
980987
AtlanCustomAttributePrimitiveType.SQL,
988+
AtlanCustomAttributePrimitiveType.RICH_TEXT,
981989
):
982990
base_type = AtlanCustomAttributePrimitiveType.STRING.value
983991
else:
@@ -1104,6 +1112,7 @@ async def _get_all_qualified_names_async(asset_type: str):
11041112
AtlanCustomAttributePrimitiveType.GROUPS,
11051113
AtlanCustomAttributePrimitiveType.URL,
11061114
AtlanCustomAttributePrimitiveType.SQL,
1115+
AtlanCustomAttributePrimitiveType.RICH_TEXT,
11071116
):
11081117
base_type = AtlanCustomAttributePrimitiveType.STRING.value
11091118
else:

pyatlan_v9/model/typedef.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,14 @@ def creator(
572572
["type"],
573573
[type],
574574
)
575+
if attribute_type == AtlanCustomAttributePrimitiveType.RICH_TEXT:
576+
primitive_type = AtlanCustomAttributePrimitiveType.STRING.value
577+
else:
578+
primitive_type = attribute_type.value
579+
575580
options = AttributeDef.Options(
576581
custom_metadata_version="v2",
577-
primitive_type=attribute_type.value,
582+
primitive_type=primitive_type,
578583
applicable_entity_types='["Asset"]',
579584
allow_search=False,
580585
max_str_length="100000000",
@@ -1007,6 +1012,7 @@ def creator(
10071012
AtlanCustomAttributePrimitiveType.GROUPS,
10081013
AtlanCustomAttributePrimitiveType.URL,
10091014
AtlanCustomAttributePrimitiveType.SQL,
1015+
AtlanCustomAttributePrimitiveType.RICH_TEXT,
10101016
):
10111017
base_type = AtlanCustomAttributePrimitiveType.STRING.value
10121018
else:
@@ -1135,6 +1141,7 @@ async def _get_all_qualified_names_async(asset_type: str):
11351141
AtlanCustomAttributePrimitiveType.GROUPS,
11361142
AtlanCustomAttributePrimitiveType.URL,
11371143
AtlanCustomAttributePrimitiveType.SQL,
1144+
AtlanCustomAttributePrimitiveType.RICH_TEXT,
11381145
):
11391146
base_type = AtlanCustomAttributePrimitiveType.STRING.value
11401147
else:

tests/unit/test_typedef_model.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,36 @@ def test_multi_value_select_setter_condition(self, client: AtlanClient):
480480
== f"array<{AtlanCustomAttributePrimitiveType.STRING.value}>"
481481
)
482482

483+
def test_string_and_rich_text_are_distinct_enum_members(self):
484+
"""Test that STRING and RICH_TEXT are distinct enum members (not aliases)"""
485+
assert (
486+
AtlanCustomAttributePrimitiveType.STRING
487+
is not AtlanCustomAttributePrimitiveType.RICH_TEXT
488+
)
489+
assert (
490+
AtlanCustomAttributePrimitiveType.STRING
491+
!= AtlanCustomAttributePrimitiveType.RICH_TEXT
492+
)
493+
assert (
494+
AtlanCustomAttributePrimitiveType.STRING.value
495+
!= AtlanCustomAttributePrimitiveType.RICH_TEXT.value
496+
)
497+
498+
def test_string_attribute_is_not_rich_text(self, client: AtlanClient):
499+
"""Test that STRING attributes do NOT have is_rich_text set"""
500+
with patch("pyatlan.model.typedef._get_all_qualified_names") as mock_get_qa:
501+
mock_get_qa.return_value = set()
502+
attr_def = AttributeDef.create(
503+
client=client,
504+
display_name="Plain String",
505+
attribute_type=AtlanCustomAttributePrimitiveType.STRING,
506+
)
507+
508+
assert attr_def.options
509+
assert attr_def.options.is_rich_text is False
510+
assert attr_def.options.primitive_type == "string"
511+
assert attr_def.type_name == "string"
512+
483513
def test_rich_text_attribute_creation(self, client: AtlanClient):
484514
"""Test that RICH_TEXT attributes are created with correct options"""
485515
with patch("pyatlan.model.typedef._get_all_qualified_names") as mock_get_qa:

0 commit comments

Comments
 (0)