Skip to content

Commit 258c41e

Browse files
authored
Merge pull request #857 from atlanhq/PART-548
PART-548 | Give RICH_TEXT a distinct enum value so STRING and RICH_TEXT are not aliases
2 parents 097ce90 + b7141f4 commit 258c41e

5 files changed

Lines changed: 151 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:
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright 2022 Atlan Pte. Ltd.
3+
from unittest.mock import patch
4+
5+
import pytest
6+
7+
from pyatlan.client.atlan import AtlanClient
8+
from pyatlan.errors import AtlanError
9+
from pyatlan.model.enums import AtlanCustomAttributePrimitiveType
10+
from pyatlan_v9.model.typedef import AttributeDef
11+
12+
13+
@pytest.fixture(autouse=True)
14+
def set_env(monkeypatch):
15+
monkeypatch.setenv("ATLAN_API_KEY", "test-api-key")
16+
monkeypatch.setenv("ATLAN_BASE_URL", "https://test.atlan.com")
17+
18+
19+
@pytest.fixture()
20+
def client():
21+
return AtlanClient()
22+
23+
24+
class TestV9AttributeDef:
25+
def test_string_and_rich_text_are_distinct_enum_members(self):
26+
"""Test that STRING and RICH_TEXT are distinct enum members (not aliases)"""
27+
assert (
28+
AtlanCustomAttributePrimitiveType.STRING
29+
is not AtlanCustomAttributePrimitiveType.RICH_TEXT
30+
)
31+
assert (
32+
AtlanCustomAttributePrimitiveType.STRING
33+
!= AtlanCustomAttributePrimitiveType.RICH_TEXT
34+
)
35+
assert (
36+
AtlanCustomAttributePrimitiveType.STRING.value
37+
!= AtlanCustomAttributePrimitiveType.RICH_TEXT.value
38+
)
39+
40+
def test_string_attribute_is_not_rich_text(self, client: AtlanClient):
41+
"""Test that STRING attributes do NOT have is_rich_text set"""
42+
with patch("pyatlan_v9.model.typedef._get_all_qualified_names") as mock_get_qa:
43+
mock_get_qa.return_value = set()
44+
attr_def = AttributeDef.creator(
45+
client=client,
46+
display_name="Plain String",
47+
attribute_type=AtlanCustomAttributePrimitiveType.STRING,
48+
)
49+
50+
assert attr_def.options
51+
assert attr_def.options.is_rich_text is False
52+
assert attr_def.options.primitive_type == "string"
53+
assert attr_def.type_name == "string"
54+
55+
def test_rich_text_attribute_creation(self, client: AtlanClient):
56+
"""Test that RICH_TEXT attributes are created with correct options"""
57+
with patch("pyatlan_v9.model.typedef._get_all_qualified_names") as mock_get_qa:
58+
mock_get_qa.return_value = set()
59+
attr_def = AttributeDef.creator(
60+
client=client,
61+
display_name="Rich Content",
62+
attribute_type=AtlanCustomAttributePrimitiveType.RICH_TEXT,
63+
description="Test rich text attribute",
64+
)
65+
66+
assert attr_def.display_name == "Rich Content"
67+
assert attr_def.type_name == AtlanCustomAttributePrimitiveType.STRING.value
68+
assert attr_def.description == "Test rich text attribute"
69+
assert attr_def.options
70+
assert attr_def.options.is_rich_text is True
71+
assert attr_def.options.multi_value_select is False
72+
73+
def test_rich_text_cannot_be_multi_valued(self, client: AtlanClient):
74+
"""Test that RICH_TEXT attributes cannot be multi-valued"""
75+
with patch("pyatlan_v9.model.typedef._get_all_qualified_names") as mock_get_qa:
76+
mock_get_qa.return_value = set()
77+
with pytest.raises(AtlanError) as exc_info:
78+
AttributeDef.creator(
79+
client=client,
80+
display_name="Invalid Rich Text",
81+
attribute_type=AtlanCustomAttributePrimitiveType.RICH_TEXT,
82+
multi_valued=True,
83+
)
84+
85+
error = exc_info.value
86+
assert "ATLAN-PYTHON-400-076" in str(error)
87+
88+
def test_rich_text_options_configuration(self, client: AtlanClient):
89+
"""Test that RICH_TEXT options are configured correctly"""
90+
with patch("pyatlan_v9.model.typedef._get_all_qualified_names") as mock_get_qa:
91+
mock_get_qa.return_value = set()
92+
attr_def = AttributeDef.creator(
93+
client=client,
94+
display_name="Rich Text Field",
95+
attribute_type=AtlanCustomAttributePrimitiveType.RICH_TEXT,
96+
)
97+
98+
options = attr_def.options
99+
assert options is not None
100+
assert options.primitive_type == AtlanCustomAttributePrimitiveType.STRING.value
101+
assert options.is_rich_text is True
102+
assert options.multi_value_select is False

0 commit comments

Comments
 (0)