Skip to content

Commit 09f35be

Browse files
cmgroteclaude
andcommitted
fix: prevent category field from being silently dropped by omit_defaults
- Change TypeDef.category to Union[AtlanTypeCategory, UnsetType] = UNSET so the base class no longer makes it required (allows absent from JSON) - Remove hardcoded category defaults from all subclasses (EnumDef, StructDef, AtlanTagDef, EntityDef, RelationshipDef, CustomMetadataDef) to prevent omit_defaults=True from dropping the field when its value equals the default - Add __post_init__ to each subclass to unconditionally set the correct AtlanTypeCategory, matching the pattern used by generated asset classes - Update test assertions from `is None` to `is msgspec.UNSET` for absent fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2a78406 commit 09f35be

3 files changed

Lines changed: 28 additions & 23 deletions

File tree

pyatlan_v9/model/typedef.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ def _get_all_qualified_names(client: AtlanClient, asset_type: str) -> Set[str]:
233233
class TypeDef(msgspec.Struct, kw_only=True, rename="camel", omit_defaults=True):
234234
"""Base type definition."""
235235

236-
category: AtlanTypeCategory
236+
category: Union[AtlanTypeCategory, msgspec.UnsetType] = msgspec.UNSET
237237
"""Type of the type definition."""
238238

239239
create_time: Union[int, None, msgspec.UnsetType] = msgspec.UNSET
@@ -327,9 +327,6 @@ def extend_elements(current: List[str], new: List[str]) -> List[str]:
327327
unique_elements.add(element)
328328
return extended_list
329329

330-
category: AtlanTypeCategory = AtlanTypeCategory.ENUM
331-
"""Type category for enumeration definitions."""
332-
333330
element_defs: Union[List[EnumDef.ElementDef], msgspec.UnsetType] = msgspec.UNSET
334331
"""Valid values for the enumeration."""
335332

@@ -339,6 +336,9 @@ def extend_elements(current: List[str], new: List[str]) -> List[str]:
339336
service_type: Union[str, None, msgspec.UnsetType] = msgspec.UNSET
340337
"""Internal use only."""
341338

339+
def __post_init__(self) -> None:
340+
self.category = AtlanTypeCategory.ENUM
341+
342342
@staticmethod
343343
def creator(name: str, values: List[str]) -> EnumDef:
344344
"""
@@ -1225,15 +1225,15 @@ class RelationshipAttributeDef(AttributeDef, kw_only=True):
12251225
class StructDef(TypeDef, kw_only=True):
12261226
"""Struct type definition."""
12271227

1228-
category: AtlanTypeCategory = AtlanTypeCategory.STRUCT
1229-
"""Type category for struct definitions."""
1230-
12311228
attribute_defs: Union[List[AttributeDef], None, msgspec.UnsetType] = msgspec.UNSET
12321229
"""List of attributes that should be available in the type definition."""
12331230

12341231
service_type: Union[str, None, msgspec.UnsetType] = msgspec.UNSET
12351232
"""Internal use only."""
12361233

1234+
def __post_init__(self) -> None:
1235+
self.category = AtlanTypeCategory.STRUCT
1236+
12371237

12381238
# =============================================================================
12391239
# ATLAN TAG DEFINITION (CLASSIFICATION)
@@ -1246,9 +1246,6 @@ class AtlanTagDef(TypeDef, kw_only=True):
12461246
attribute_defs: Union[List[AttributeDef], None, msgspec.UnsetType] = msgspec.UNSET
12471247
"""Unused."""
12481248

1249-
category: AtlanTypeCategory = AtlanTypeCategory.CLASSIFICATION
1250-
"""Type category for classification definitions."""
1251-
12521249
display_name: Union[str, None, msgspec.UnsetType] = msgspec.UNSET
12531250
"""Name used for display purposes (in user interfaces)."""
12541251

@@ -1272,6 +1269,9 @@ class AtlanTagDef(TypeDef, kw_only=True):
12721269
)
12731270
"""TBC"""
12741271

1272+
def __post_init__(self) -> None:
1273+
self.category = AtlanTypeCategory.CLASSIFICATION
1274+
12751275
@staticmethod
12761276
def creator(
12771277
name: str,
@@ -1337,9 +1337,6 @@ class EntityDef(TypeDef, kw_only=True):
13371337
] = msgspec.UNSET
13381338
"""Unused."""
13391339

1340-
category: AtlanTypeCategory = AtlanTypeCategory.ENTITY
1341-
"""Type category for entity definitions."""
1342-
13431340
relationship_attribute_defs: Union[
13441341
List[RelationshipAttributeDef], msgspec.UnsetType
13451342
] = msgspec.UNSET
@@ -1354,6 +1351,9 @@ class EntityDef(TypeDef, kw_only=True):
13541351
super_types: Union[List[str], msgspec.UnsetType] = msgspec.UNSET
13551352
"""List of super-types that this type definition extends."""
13561353

1354+
def __post_init__(self) -> None:
1355+
self.category = AtlanTypeCategory.ENTITY
1356+
13571357
@property
13581358
def reserved_type(self) -> bool:
13591359
"""Whether this entity definition is a reserved (built-in) type."""
@@ -1408,9 +1408,6 @@ class RelationshipDef(TypeDef, kw_only=True):
14081408
attribute_defs: Union[List[AttributeDef], msgspec.UnsetType] = msgspec.UNSET
14091409
"""Unused."""
14101410

1411-
category: AtlanTypeCategory = AtlanTypeCategory.RELATIONSHIP
1412-
"""Type category for relationship definitions."""
1413-
14141411
end_def1: Union[RelationshipEndDef, None, msgspec.UnsetType] = msgspec.UNSET
14151412
"""Definition for the first endpoint of the relationship."""
14161413

@@ -1440,6 +1437,9 @@ class RelationshipDef(TypeDef, kw_only=True):
14401437
super_types: Union[List[str], msgspec.UnsetType] = msgspec.UNSET
14411438
"""List of super-types that this relationship type extends."""
14421439

1440+
def __post_init__(self) -> None:
1441+
self.category = AtlanTypeCategory.RELATIONSHIP
1442+
14431443

14441444
# =============================================================================
14451445
# CUSTOM METADATA DEFINITION
@@ -1524,15 +1524,15 @@ def with_logo_from_icon(
15241524
attribute_defs: Union[List[AttributeDef], msgspec.UnsetType] = msgspec.UNSET
15251525
"""List of custom attributes defined within the custom metadata."""
15261526

1527-
category: AtlanTypeCategory = AtlanTypeCategory.CUSTOM_METADATA
1528-
"""Type category for custom metadata definitions."""
1529-
15301527
display_name: Union[str, None, msgspec.UnsetType] = msgspec.UNSET
15311528
"""Name used for display purposes (in user interfaces)."""
15321529

15331530
options: Union[CustomMetadataDef.Options, None, msgspec.UnsetType] = msgspec.UNSET
15341531
"""Optional properties of the type definition."""
15351532

1533+
def __post_init__(self) -> None:
1534+
self.category = AtlanTypeCategory.CUSTOM_METADATA
1535+
15361536
@staticmethod
15371537
def creator(
15381538
display_name: str, description: Optional[str] = None

tests_v9/unit/aio/test_custom_metadata.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Copyright 2025 Atlan Pte. Ltd.
33
from unittest.mock import AsyncMock, patch
44

5+
import msgspec
56
import pytest
67

78
from pyatlan_v9.client.aio.atlan import AsyncAtlanClient
@@ -553,4 +554,6 @@ async def async_generator():
553554
# Cannot be multi-valued
554555
assert options.multi_value_select is False
555556
# Should not have custom_type set (that's for SQL, URL, etc.)
556-
assert not hasattr(options, "custom_type") or options.custom_type is None
557+
assert (
558+
not hasattr(options, "custom_type") or options.custom_type is msgspec.UNSET
559+
)

tests_v9/unit/test_typedef_model.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def check_property(property_name: str):
9696
if key in source:
9797
assert value == source[key]
9898
else:
99-
assert value is None
99+
assert value is msgspec.UNSET
100100

101101
check_property("create_time")
102102
check_property("created_by")
@@ -120,7 +120,7 @@ def check_attribute(model: object, attribute_name: str, source: dict):
120120
else:
121121
# Since "options" are now initialized with a default factory
122122
if attribute_name != "options":
123-
assert getattr(model, attribute_name) is None
123+
assert getattr(model, attribute_name) is msgspec.UNSET
124124

125125

126126
def check_has_attributes(type_def: TypeDef, type_def_json: dict):
@@ -588,4 +588,6 @@ def test_rich_text_options_configuration(self, client: AtlanClient):
588588
# Cannot be multi-valued
589589
assert options.multi_value_select is False
590590
# Should not have custom_type set (that's for SQL, URL, etc.)
591-
assert not hasattr(options, "custom_type") or options.custom_type is None
591+
assert (
592+
not hasattr(options, "custom_type") or options.custom_type is msgspec.UNSET
593+
)

0 commit comments

Comments
 (0)